c语言file的用法(C深入理解EOF和流FILE标识)

The C Standard Input and Output Library (stdio.h) uses what are called streams to operate with physical devices such as keyboards, printers, terminals or with any other type of Files supported by the system. Streams are an abstraction to interact with these in an uniform way; All streams have similar properties independently of the individual characteristics of the physical media they are associated with.,接下来我们就来聊聊关于c语言file的用法?以下内容大家不妨参考一二希望能帮到您!

c语言file的用法(C深入理解EOF和流FILE标识)

c语言file的用法

The C Standard Input and Output Library (stdio.h) uses what are called streams to operate with physical devices such as keyboards, printers, terminals or with any other type of Files supported by the system. Streams are an abstraction to interact with these in an uniform way; All streams have similar properties independently of the individual characteristics of the physical media they are associated with.

C标准输入和输出库(stdio.h)在执行输入和输出操作使用所谓的流来操作物理设备,如键盘、打印机、终端或系统支持的任何其他类型的文件。流是以统一方式与这些流交互的抽象;所有流都具有类似的属性,独立于它们所关联的物理介质的各个特征。

Streams are handled in the stdio.h library as pointers to FILE objects. A pointer to a FILE object uniquely identifies a stream, and is used as a parameter in the operations involving that stream.

流在stdio.h库中作为指向文件(FILE)对象的指针进行处理。指向文件对象的指针唯一标识流,并在涉及该流的操作中用作参数。

struct _iobuf { char *_ptr; // 文件输入的下一个位置 int _cnt; // 当前缓冲区的相对位置 char *_base; // 文件的起始位 int _flag; // 文件标志 int _file; // 有效性验证 int _charbuf; // 缓冲区的检査,若无此成员,则不读取 int _bufsiz; // 文件大小 char *_tmpfname; // 临时文件名 }; typedef struct _iobuf FILE; // 标识一个特定流

There also exist three standard streams: stdin, stdout and stderr, which are automatically created and opened for all programs using the library.

还有三个标准流:stdin、stdout和stderr,它们是为使用库的所有程序自动创建和打开的。

Streams have some properties that define which functions can be used on them and how these will treat the data input or output through them. Most of these properties are defined at the moment the stream is associated with a file (opened) using the fopen function:

流具有一些属性,这些属性定义了可以在其上使用哪些函数,以及这些函数将如何处理通过它们输入或输出的数据。其中大多数属性是在流与文件(打开)关联时使用fopen函数定义的:

A buffer is a block of memory where data is accumulated before being physically read or written to the associated file or device. Streams can be either fully buffered, line buffered or unbuffered. On fully buffered streams, data is read/written when the buffer is filled, on line buffered streams this happens when a new-line character is encountered, and on unbuffered streams characters are intended to be read/written as soon as possible.

缓冲区是一块内存,数据在物理读写到相关文件或设备之前会在其中累积。流可以是完全缓冲的、行缓冲的或非缓冲的。在完全缓冲的流中,数据在缓冲区填满时读取/写入;在行缓冲流中,当遇到新行字符时会发生这种情况;在非缓冲流中,要尽快读取/写入字符。

Streams have certain internal indicators that specify their current state and which affect the behavior of some input and output operations performed on them:

流具有特定的内部指示器,用于指定其当前状态,并影响对其执行的某些输入和输出操作的行为(设置FILE的_flag):

Error indicator 错误指示器

This indicator is set when an error has occurred in an operation related to the stream. This indicator can be checked with the ferror function, and can be reset by calling either to clearerr, freopen or rewind.

此指示器在与流相关的操作中发生错误时设置。该指示器可通过ferror功能进行检查,并可通过调用clearerr、freopen或rewind进行重置。

End-Of-File indicator 文件结束指示器

When set, indicates that the last reading or writing operation performed with the stream reached the End of File. It can be checked with the fEOF function, and can be reset by calling either to clearerr or freopen or by calling to any repositioning function (rewind, fseek and fsetpos).

设置时,表示使用流执行的最后一次读取或写入操作已到达文件末尾。可以使用feof功能进行检查,也可以通过调用clearerr或freopen或调用任何重新定位功能(rewind、fseek和fsetpos)进行重置。

Position indicator 位置指示器

It is an internal pointer of each stream which points to the next character to be read or written in the next I/O operation. Its value can be obtained by the ftell and fgetpos functions, and can be changed using the repositioning functions rewind, fseek and fsetpos.

它是每个流的内部指针,指向下一个I/O操作中要读取或写入的下一个字符。其值可通过ftell和fgetpos函数获得,并可使用重新定位函数rewind、fseek和fsetpos进行更改。

1 eof(End-of-File)

EOF只是fgetc()的返回值的宏。

EOF is a macro definition of type int that expands into a negative integral constant expression (generally, -1).

EOF是int类型的宏定义,扩展为负整数常量表达式(通常为,-1)。

#define EOF (-1) // EOF 标志在标准输入中由ctrl d(liunx下)或者ctrl z(win下)产生。

It is used as the value returned by several functions in header <stdio.h> to indicate that the End-of-File has been reached or to signal some other failure conditions.

它被用作头文件<stdio.h>中多个函数返回的值,以指示已到达文件末尾或指示其他一些故障条件。

It is also used as the value to represent an invalid character.

它还用作表示无效字符的值。

In C , this macro corresponds to the value of char_traits<char>::eof().

在C 中,此宏对应于char_traits<char>::eof()的值。

3 流如何设置文件结尾?

get一簇的一些函数的源码都会使用_getc_lk(_stream)宏,该宏有在流中设置文件末尾标识,这里的文件末尾标识并不是EOF(-1的宏),而是设置FILE的_flag的一个位,并使用feof()来检测:

#define _getc_lk(_stream) (--(_stream)->_cnt >= 0 ? 0xff & *(_stream)->_ptr : _filbuf(_stream)) /* _MTHREAD_ONLY */ _filbuf()实现中有以下代码: // …… stream->_flag |= stream->_cnt ? _IOERR : _IOEOF; // …… #define _IOEOF 0x0010 #define feof(_stream) ((_stream)->_flag & _IOEOF) // #define EOF (-1)

4 函数返回的EOF

只有fgetc()返回EOF.

int fgetc ( FILE * stream ); #define EOF (-1)

Get character from stream

从流中获取字符

* returns the character read

该函数以无符号 char 强制转换为 int 的形式返回读取的字符

* returns EOF if at end of file or error occurred

,如果到达文件末尾或发生读错误,则返回 EOF。

Returns the character currently pointed by the internal file position indicator of the specified stream. The internal file position indicator is then advanced to the next character.

返回指定流的内部文件位置指示器当前指向的字符。然后,内部文件位置指示器前进到下一个字符。

If the stream is at the end-of-file when called, the function returns EOF and sets the end-of-file indicator for the stream.

如果调用时流位于文件末尾,则函数返回EOF并设置流的文件结尾指示符(可用feof()检测)。

If a read error occurs, the function returns EOF and sets the error indicator for the stream (ferror).

如果发生读取错误,函数将返回EOF并设置流的错误指示器(ferror)。

fgetc and getc are equivalent, except that getc may be implemented as a macro in some libraries.

/* fgetc example: money counter */ #include <stdio.h> int main () { FILE * pFile; int c; int n = 0; pFile=fopen ("myfile.txt","r"); if(pFile==NULL) perror ("Error opening file"); else { do { c = fgetc (pFile); if(c == '$') n ; } while(c != EOF); // 在fgetc()调用后使用EOF fclose (pFile); printf ("The file contains %d dollar sign characters ($).\n",n); } return 0; }

fgetc和getc是等效的,只是getc可以在某些库中作为宏实现,或者直接调用fgetc:

int __cdecl getc ( FILE *stream ) { return fgetc(stream); }

getchar()是getc()的宏实现:

#define getchar() getc(stdin)

4 使用feof()检测流中的文件末尾标识,实质是检测FILE的_flag的低2位

Checks whether the end-of-File indicator associated with stream is set, returning a value different from zero if it is.

检查是否设置了与流关联的文件结束指示符,如果设置了,则返回一个不同于零的值。

#define _IOEOF 0x0010 #define feof(_stream) ((_stream)->_flag & _IOEOF) // #define EOF (-1)

This indicator is generally set by a previous operation on the stream that attempted to read at or past the end-of-file.

此指示符通常由试图在文件结尾处或之后读取的流上的前一个操作设置(含有get的库函数)。

#define _getc_lk(_stream) (--(_stream)->_cnt >= 0 ? 0xff & *(_stream)->_ptr : _filbuf(_stream)) /* _MTHREAD_ONLY */ _filbuf()实现中有以下代码: // …… stream->_flag |= stream->_cnt ? _IOERR : _IOEOF; // ……

Notice that stream's internal position indicator may point to the end-of-file for the next operation, but still, the end-of-file indicator may not be set until an operation attempts to read at that point.

请注意,流的内部位置指示器可能会指向下一个操作的文件结尾,但在操作尝试在该点读取之前,可能不会设置文件结尾指示器。

This indicator is cleared by a call to clearerr, rewind, fseek, fsetpos or freopen. Although if the position indicator is not repositioned by such a call, the next i/o operation is likely to set the indicator again.

调用clearerr、rewind、fseek、fsetpos或freopen可清除此指示器。虽然如果位置指示器未通过此类调用重新定位,但下一次输入/输出操作可能会再次设置指示器。

/* feof example: byte counter */ #include <stdio.h> int main () { FILE * pFile; int n = 0; pFile = fopen ("myfile.txt","rb"); if(pFile==NULL) perror ("Error opening file"); else { while(fgetc(pFile) != EOF) { // EOF也有可能是读写错误返回的值 n; } if(feof(pFile)) { puts ("End-of-File reached."); printf ("Total number of bytes read: %d\n", n); } else puts ("End-of-File was not reached."); fclose (pFile); } return 0; }

检测文件是否到达末尾自然推荐使用feof(),函数fgetc()返回EOF的情形不仅只是到达文件末尾,还有读写错误的情况。

#include <stdio.h> #include <stdlib.h> int main(void) { FILE* fp = fopen("test.txt", "r"); if(!fp) { perror("File opening failed"); return EXIT_FAILURE; } int c; // 注意:int,非char,要求处理EOF while ((c = fgetc(fp)) != EOF) { // 标准C I/O读取文件循环 putchar(c); } if (ferror(fp)) puts("I/O error when reading"); else if (feof(fp)) puts("End of file reached successfully"); fclose(fp); }

ref:

http://m.cplusplus.com/reference/cstdio/

-End-

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页