C - 文件输入/输出


最后一章解释了C编程语言处理的标准输入和输出设备。本章介绍 C 程序员如何创建、打开、关闭用于数据存储的文本或二进制文件。

文件表示字节序列,无论它是文本文件还是二进制文件。C 编程语言提供对高级函数的访问以及低级(操作系统级)调用来处理存储设备上的文件。本章将带您了解文件管理的重要调用。

打开文件

您可以使用fopen( )函数创建新文件或打开现有文件。此调用将初始化FILE类型的对象,其中包含控制流所需的所有信息。该函数调用的原型如下 -

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

这里,文件名是一个字符串文字,您将用它来命名您的文件,访问模式可以具有以下值之一 -

先生。 模式及说明
1

r

打开现有文本文件以供阅读。

2

w

打开文本文件进行写入。如果不存在,则创建一个新文件。在这里,您的程序将从文件的开头开始写入内容。

3

A

打开文本文件以追加模式写入。如果不存在,则创建一个新文件。在这里,您的程序将开始在现有文件内容中附加内容。

4

r+

打开文本文件以进行读取和写入。

5

瓦+

打开文本文件以进行读取和写入。如果文件存在,它首先将其截断为零长度,否则创建一个文件(如果不存在)。

6

一个+

打开文本文件以进行读取和写入。如果文件不存在,它将创建该文件。阅读会从头开始,但写作只能追加。

如果您要处理二进制文件,那么您将使用以下访问模式而不是上面提到的访问模式 -

"rb", "wb", "ab", "rb+", "r+b", "wb+", "w+b", "ab+", "a+b"

关闭文件

要关闭文件,请使用 fclose( ) 函数。该函数的原型是 -

int fclose( FILE *fp );

fclose (-)函数成功时返回零,如果关闭文件时出错则返回EOF 。该函数实际上将缓冲区中仍待处理的所有数据刷新到文件,关闭文件,并释放用于该文件的所有内存。EOF 是头文件stdio.h中定义的常量。

C 标准库提供了各种函数来逐个字符或以固定长度字符串的形式读写文件。

写入文件

以下是将单个字符写入流的最简单的函数 -

int fputc( int c, FILE *fp );

函数fputc()将参数 c 的字符值写入 fp 引用的输出流。如果成功则返回写入的字符,如果出现错误则返回EOF 。您可以使用以下函数将空终止字符串写入流 -

int fputs( const char *s, FILE *fp );

函数fputs()将字符串s写入 fp 引用的输出流。成功时返回一个非负值,否则如果出现任何错误,则返回EOF 。您也可以使用int fprintf(FILE *fp,const char *format, ...)函数将字符串写入文件。尝试以下示例。

确保/tmp目录可用。如果不是,则在继续之前,您必须在计算机上创建此目录。

#include <stdio.h>

main() {
   FILE *fp;

   fp = fopen("/tmp/test.txt", "w+");
   fprintf(fp, "This is testing for fprintf...\n");
   fputs("This is testing for fputs...\n", fp);
   fclose(fp);
}

当上面的代码被编译并执行时,它会在 /tmp 目录中创建一个新文件test.txt并使用两个不同的函数写入两行。让我们在下一节中阅读该文件。

读取文件

下面给出的是从文件中读取单个字符的最简单的函数 -

int fgetc( FILE * fp );

fgetc ()函数从 fp 引用的输入文件中读取一个字符。返回值是读取的字符,如果出现任何错误,则返回EOF。以下函数允许从流中读取字符串 -

char *fgets( char *buf, int n, FILE *fp );

函数fgets()从 fp 引用的输入流中读取最多 n-1 个字符。它将读取的字符串复制到缓冲区buf中,并附加一个字符来终止该字符串。

如果此函数在读取最大字符数之前遇到换行符 '\n' 或文件末尾 EOF,则它仅返回到该点读取的字符(包括换行符)。您还可以使用int fscanf(FILE *fp, const char *format, ...)函数从文件中读取字符串,但遇到第一个空格字符后会停止读取。

#include <stdio.h>

main() {

   FILE *fp;
   char buff[255];

   fp = fopen("/tmp/test.txt", "r");
   fscanf(fp, "%s", buff);
   printf("1 : %s\n", buff );

   fgets(buff, 255, (FILE*)fp);
   printf("2: %s\n", buff );
   
   fgets(buff, 255, (FILE*)fp);
   printf("3: %s\n", buff );
   fclose(fp);

}

当上面的代码被编译和执行时,它会读取上一节中创建的文件并产生以下结果 -

1 : This
2: is testing for fprintf...

3: This is testing for fputs...

让我们更详细地了解这里发生的事情。首先,fscanf()只读取This,因为在那之后,它遇到了一个空格,第二次调用是fgets(),它读取剩余的行,直到遇到行尾。最后,最后一次调用fgets()完整读取第二行。

二进制 I/O 函数

有两个函数可用于二进制输入和输出 -

size_t fread(void *ptr, size_t size_of_elements, size_t number_of_elements, FILE *a_file);
              
size_t fwrite(const void *ptr, size_t size_of_elements, size_t number_of_elements, FILE *a_file);

这两个函数都应该用于读取或写入内存块 - 通常是数组或结构。