C读写文件

简介

C 语言库 <stdio.h> 中的 IO操作也可以在 C++ 中使用,如果为了考虑效率与内存使用问题,推荐使用 C 语言处理 C++ 中文件操作。

流属性

<stdio.h> 中的函数处理文件用的是流,是物理设备无关性的。流有一些属性,是在使用 fopen 打开文件时就定义了的:

Read/Write Access:读、写、读写

Text/Binary:Text 流代表了文本行集,每行以换行符结束;Binary 流直接读取物理设备中的字符。

Buffer:流可以全缓冲、行缓冲、不缓冲

Orientation:流处理方向

指示符

流有一些内部指示符指定当前状态并影响流执行的输入输出操作:

Error 指示符:当流操作出错时将设置此指示符,可以使用 ferror 函数检查此指示符,也可以使用函数 clearerrfreopenrewind 重置此指示符。

EOF 指示符:当 EOF 指示符被设置的时候,表示到达了文件结尾,可以使用 feof 函数检查此指示符,也可以调用函数 clearerrfreopen 或重新定位函数 rewindfseekfsetpos 重置EOF指示符。

Position 指示符:流内部的位置指示符,指向下一个 IO 操作中要读取或写入的下一个字符。它的值可以通过 ftellfgetpos 函数获得,并且可以使用重新定位函数rewindfseekfsetpos 进行更改。

函数

Operations on files

  • int remove(const char *filename);

  • int rename(const char *oldname, const char *newname);

    rename、remove 函数成功时返回值为0,失败时非 0。

  • FILE *tmpfile (void);

    临时文件创建成功时返回流指针,失败时返回 NULL 。在程序结束时,临时文件将删除。

  • char *tmpnam(char *str);

    需要配合 fopen 才能创建临时文件,与 tmpfile 不同,在程序结束时,需要调用 remove 删除文件。

    NOTE:若 str为 NULL,tmpnam 函数将返回指向内部缓冲区的字符串,其中的值将保存到下一次调用 tmpnam 函数为止。若 str 不为 空,则 tmpnam 函数返回 str 指针。若函数无法创建合适的文件名,将返回 NULL 指针。

File access

  • FILE * fopen ( const char * filename, const char * mode );

    返回的流将使用完全缓冲。通过 fclose 或 freopen 函数将返回的指针与文件解除关联。

    mode 参数值如下:

    mode含义
    “r”read: 打开一个文件用于输入,文件必须存在。
    “w”write:创建一个空文件。如果文件已存在,
    将删除原内容并视为一个新的空文件。
    “a”append:在文件尾部追加内容,若文件不存在将新建它。
    重定位函数fseek、fsetpos、rewind 将被忽略。
    “r+”read/update:打开一个文件用于输入输出,文件必须存在。
    “w+”write/update:新建一个文件用于输入输出。如果文件已存在,
    将删除原内容并视为一个新文件。
    “a+”append/update:打开一个文件用于输入输出。在文件尾部追加内容,
    若文件不存在将新建它。重定位函数(fseek,fsetpos,rewind)会
    影响下一个输入操作,但输出操作会将位置移回文件末尾。
    “b”与上面六个模式一起使用表示是二进制文件读写。
    "rb", "wb", "ab","rb+" ("r+b"), "wb+" ( "w+b"), "ab+" ("a+b")
    “x”C2011非C++标准。”x”与”w”一起使用表示文件存在函数将失败而不是覆盖它。

    在某些库实现中,打开或创建具有更新模式的文本文件可能会将流视为二进制文件。

    NOTE:在使用 “+” 模式时,在写入操作之后的读取操作之前,流应被刷新(fflush)或重新定位(fseek,fsetpos,rewind)。在读取操作之后的写入操作之前(无论何时该操作未到达文件结尾),流都应重新定位(fseek,fsetpos,rewind)。

  • int fclose(FILE *stream);

    关闭流并不再与文件关联。内部缓冲区也不再关联并冲刷,输出缓冲区中未写的内容将写入,输入缓冲区中未读的内容将被丢弃。即使函数调用失败,流标识符也不再与文件关联。

  • int fflush(FILE *stream);

    如果 stream 是空指针,冲刷所有流。如果发生错误,则返回EOF并设置错误指示符。

  • FILE * freopen ( const char * filename, const char * mode, FILE * stream );

    若 filename 指定新文件,freopen 函数将尝试 close 流,并打开新文件并关联到此流指示符。 若 filename 是空指针,freopen 函数将改变流模式。 错误指示符和 EOF 指示符将自动清除。 若文件重新打开失败,返回空指针。

  • void setbuf ( FILE * stream, char * buffer );

    若 buffer 不是空指针,将设置 buffer 为流 stream 的缓冲区,该缓冲区将成为完全缓冲的流。 若buffer 是空指针,该缓冲区将成为无缓冲的流。 buffer 至少为 BUFSIZ 字节大小。

  • int setvbuf ( FILE * stream, char * buffer, int mode, size_t size );

    setvbuf 函数指定缓冲区的模式和大小(以字节为单位)。如果buffer是一个空指针,该函数会自动分配一个 size 字节缓冲区。否则,buffer 指向的数组可以用作 size 字节的缓冲区。此函数可用于重新定义缓冲区大小或模式,定义用户分配的缓冲区或禁用流的缓冲。

    _IOFBF:全缓冲,_IOLBF:行缓冲,_IONBF:无缓冲。

Formatted input/output

  • int fprintf ( FILE * stream, const char * format, ... );

    将格式化数据写入流。成功时,返回写入的字符总数。失败时,设置 ferror 指示符并返回负数。 NOTE:写入宽字符时发生多字节字符编码错误,则将 errno 设置为 EILSEQ 并返回负数。

  • int fscanf ( FILE * stream, const char * format, ... );

    从流中读取格式化数据。成功时,返回填充项目的个数。如果在读取时发生读取错误或达到文件结尾,则设置相应的指示符(feof或ferror)。并且,如果在成功读取任何数据之前发生了任何一个,则返回EOF。

  • int printf ( const char * format, ... );

    将格式化数据打印到stdout。返回值参考 fprintf。

  • int scanf ( const char * format, ... );

    从stdin读取格式化数据。返回值参考 fscanf。

  • int snprintf ( char * s, size_t n, const char * format, ... );

    将格式化输出写入n字节的缓冲区。生成的字符串的长度最多为n-1,为附加的终止空字符留出空间。如果发生编码错误,则返回负数。只有当此返回值为非负且小于n时,才会完全写入该字符串。

  • int sprintf ( char * str, const char * format, ... );

    成功时,返回写入的字符总数。此计数不包括自动附加在字符串末尾的附加空字符。 失败时,返回负数。使用更安全的函数 snprintf。

  • int sscanf ( const char * s, const char * format, ...);

    从字符串中读取格式化数据。类似于函数 scanf,数据来源于字符串。

Character input/output

  • int fgetc ( FILE * stream );

    返回指定流的内部文件位置指示符当前指向的字符。然后内部文件位置指示器前进到下一个字符。到达结尾时返回 EOF,并设置 EOF 指示符。读取错误时,返回 EOF 并设置错误指示符。

  • char * fgets ( char * str, int num, FILE * stream );

    读取 num-1 个字符、读取到换行符或到达文件结尾时结束。换行符导致函数读取结束,但它也被复制到 str 中。函数结束时,将在字符串中自动添加 ‘\0’ 字符。 已经处于文件结尾再读取字符将导致函数 fgets 返回 NULL 指针,并且不修改 str 中的内容。读取错误时,返回 NULL 指针并设置错误指示符,str 中的内容可能已经被修改。

  • int fputc ( int character, FILE * stream );

    将字符写入流,并推进文件位置指示符。写入成功时,返回该字符;写入错误时,则返回EOF并设置错误指示符。

  • int fputs ( const char * str, FILE * stream );

    从 str 字符串中开始复制,直到到达终止空字符('\0')。终止字符不会复制到流中。 成功时,返回非负值。 出错时,该函数返回 EOF 并设置错误指示符。

  • int getc ( FILE * stream );

    等价于 fgetc。getc 可能实现为宏。

  • int getchar ( void );

    等价于 getc( stdin );

  • char * gets ( char * str );

    从 stdin 中读取字符串,直到出现换行符或 EOF 。复制到 str 后的字符后会自动附加终止空字符。与 fgets 不同,换行符不会添加到字符串中,而且有可能会导致缓冲区溢出。返回情况与 fgets 基本一致。不建议使用本函数,使用 fgets(str, num, stdin) 代替。

  • int putc ( int character, FILE * stream );

    等价于 fputc。putc 可能实现为宏。

  • int puts ( const char * str );

    将 str 指向的 C 字符串写入 stdout 直到到达 ‘\0’。末尾会附加 ‘’,这与 fputs 不同。返回值情况与 fputs 一致。

  • int ungetc ( int character, FILE * stream );

    将字符放回到流中,就好像撤销了 fgetc 一样。该字符可以与之前从流中读取的字符不同。 在任何情况下,从流中读取的下一个字符是传递给该函数的字符,与原始字符无关。 在流上调用 fseek、fsetpos 或 rewind将丢弃之前使用此函数返回的任何字符。 如果字符是EOF,则操作失败并且输入流保持不变。 成功时,返回回放的字符;失败时,返回 EOF。

Direct input/output

  • size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );

    从流中读取数据块。成功时,返回元素的个数。若个数与 count 不同,则表示到达了文件结尾或读取错误,检查对应的指示符。size 或 count 为零,则函数不进行任何操作。

  • size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );

    将数据块写入到流中。成功时,返回成功写入的元素总数。若此数字与 count 不同,则设置错误指示符。size 或 count 为零,则函数不进行任何操作。

File positioning

  • int fgetpos ( FILE * stream, fpos_t * pos );

    获取重定位流位置指示符。成功时,返回 0;失败时,设置 errno 值并返回非零值。

  • int fseek ( FILE * stream, long int offset, int origin );

    将与流关联的位置指示符设置为新位置。 对于在二进制模式下打开的流,offset + origin 就是新位置。 对于在文本模式下打开的流,offset应为 0 或前一次调用 ftell 返回的值,而 origin 必须为 SEEK_SET(文件开始处)。 成功时,返回 0;读写错误时,设置 errno 值并返回非零值。

  • int fsetpos ( FILE * stream, const fpos_t * pos );

    设置流的位置指示符。成功时,返回 0;读写错误时,设置 errno 值并返回非零值。

  • long int ftell ( FILE * stream );

    返回流的位置指示符的当前值。对于二进制流,这是从文件开头的字节数。对于文本流,数值可能没有意义但仍可用于稍后使用fseek将位置恢复到相同位置(如果使用ungetc放回的字符仍待处于读取状态,则行为未定义)。 成功时,返回位置指示符的当前值。 失败时,返回 -1L,并将 errno 设置为系统特定的正值。

  • void rewind ( FILE * stream );

    将流的位置设置为开头。

Error-handling

  • void clearerr ( FILE * stream );

    清除流的错误和eof指示符。函数 rewind, fseek, fsetpos and freopen 也可以清除它们。

  • int feof ( FILE * stream );

    检查是否设置了 EOF 指示符,如果是则返回非零值。

  • int ferror ( FILE * stream );

    检查是否设置了与流关联的错误指示符,如果是,则返回不等于零的值。

  • void perror ( const char * str );

    将 errno 的值解释为错误消息,并将其打印到 stderr,可选地在其前面加上str中指定的自定义消息。

本文结束感谢您的阅读
感谢打赏,继续前行!