Cprogramming 简明教程

File Handling in C

File Handling in C

File handling in C 是以使用C语言函数创建、打开、写入数据、读取数据、重命名和删除等文件操作处理的过程。借助这些函数,我们可以执行文件操作,以将数据存储和检索到/从程序中的文件。

Need of File Handling in C

如果我们使用C程序执行输入和输出操作,数据将存在于程序运行期间,当程序终止时,我们将无法再次使用该数据。 File handling 需要处理存储在外部内存中的文件,即存储和访问计算机外部内存中的信息。你可以使用文件处理永久保存数据。

Types of Files

文件表示一系列字节。有两种类型的文件: text filesbinary files -

FILE Pointer (File*)

在处理 file handling 时,需要一个 file pointer 来存储fopen()函数返回的 FILE 结构的引用。文件指针是所有文件处理操作所必需的。

fopen() function 返回 FILE 类型的指针。 FILEstdio.h 中预定义的结构类型,包含文件描述符、大小和位置等属性。

typedef struct {
   int fd;			/* File descriptor */
   unsigned char *buf;	/* Buffer */
   size_t size;		/* Size of the file */
   size_t pos;		/* Current position in the file */
} FILE;

Declaring a File Pointer (FILE*)

以下是声明文件指针的语法 −

FILE* file_pointer;

Opening (Creating) a File

必须打开一个文件才能执行任何操作。 fopen() 函数用于创建新文件或打开现有文件。您需要指定您想要打开文件的模式。下面说明了各种文件打开模式,其中任何一个模式都可以在创建/打开文件期间使用。

fopen() 函数返回 FILE 指针,该指针将用于其他操作,如读写和关闭文件。

Syntax

以下是打开文件的语法 −

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

此处, filename 是要打开的文件的名称, mode 定义文件的打开模式。

File Opening Modes

文件访问模式默认情况下以文本或 ASCII 模式打开文件。如果您要处理二进制文件,则您将使用以下访问模式替代上述访问模式:

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

可以以各种模式打开文件。以下是不同的文件打开模式 −

Mode

Description

r

打开一个现有文本文件以供读取。

w

打开一个文本文件以供写入。如果文件不存在,则创建一个新文件。在此处,您的程序将开始从文件开头写入内容。

a

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

r+

同时打开一个文本文件以供读取和写入。

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

a+

同时打开一个文本文件以供读取和写入。如果文件不存在,则创建文件。读取将从开头开始,但只能附加写入。

Example of Creating a File

在以下示例中,我们正在创建一个新文件。创建新文件的文件模式将是 " w "(写模式)。

#include <stdio.h>

int main() {
  FILE * file;

  // Creating a file
  file = fopen("file1.txt", "w");

  // Checking whether file is
  // created or not
  if (file == NULL) {
    printf("Error in creating file");
    return 1;
  }
  printf("File created.");

  return 0;
}
File created.

Example of Opening a File

在以下示例中,我们正在打开一个现有文件。打开现有文件的文件模式将是 " r "(只读)。您还可以使用上面说明的其他文件打开模式选项。

Note: 必须有一个文件要打开。

#include <stdio.h>

int main() {
  FILE * file;

  // Opening a file
  file = fopen("file1.txt", "r");

  // Checking whether file is
  // opened or not
  if (file == NULL) {
    printf("Error in opening file");
    return 1;
  }
  printf("File opened.");

  return 0;
}
File opened.

Closing a File

在对文件执行操作后必须关闭每个文件。 fclose() function 关闭打开的文件。

Syntax

以下是 fclose() 函数的语法 −

int fclose(FILE *fp);

fclose() 函数在成功时返回零,如果关闭文件时出错则返回 EOF。

fclose() 函数实际上将缓冲区中仍然挂起的任何数据刷新到文件,关闭文件,并释放用于该文件的任何内存。EOF 是在头文件 stdio.h. 中定义的常量

Example of Closing a File

在下面的示例中,我们将关闭一个已打开的文件 -

#include <stdio.h>

int main() {
  FILE * file;

  // Opening a file
  file = fopen("file1.txt", "w");

  // Checking whether file is
  // opened or not
  if (file == NULL) {
    printf("Error in opening file");
    return 1;
  }
  printf("File opened.");

  // Closing the file
  fclose(file);
  printf("\nFile closed.");

  return 0;
}
File opened.
File closed.

Writing to a Text File

提供了以下库函数来写入以可写模式打开的文件中的数据 -

  1. fputc() :将单个字符写入文件。

  2. fputs() :将字符串写入文件。

  3. fprintf() :将格式化字符串(数据)写入文件。

Writing Single Character to a File

fputc() function 是一个未格式化的函数,它将参数 "c" 的单个字符值写入由 " fp " 引用的输出流中。

int fputc(int c, FILE *fp);

在以下代码中,将给定字符数组中的一个字符写入以 " w " 模式打开的文件中:

#include <stdio.h>

int main() {

   FILE *fp;
   char * string = "C Programming tutorial from TutorialsPoint";
   int i;
   char ch;

   fp = fopen("file1.txt", "w");

   for (i = 0; i < strlen(string); i++) {
      ch = string[i];
      if (ch == EOF)
         break;
      fputc(ch, fp);
   }
   printf ("\n");
   fclose(fp);

   return 0;
}

Output

After executing the program, "file1.txt" will be created in the current folder and the string is written to it.

Writing String to a File

fputs() function 将字符串 "s" 写入由 "fp" 引用的输出流中。成功时它返回一个非负值,否则在发生任何错误的情况下返回 EOF。

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

以下程序将给定二维字符数组中的字符串写入文件中 -

#include <stdio.h>

int main() {

   FILE *fp;
   char *sub[] = {"C Programming Tutorial\n", "C++ Tutorial\n", "Python Tutorial\n", "Java Tutorial\n"};
   fp = fopen("file2.txt", "w");

   for (int i = 0; i < 4; i++) {
      fputs(sub[i], fp);
   }

   fclose(fp);

   return 0;
}

Output

当程序运行时,将在当前文件夹中创建一个名为 "file2.txt" 的文件,并保存以下行 -

C Programming Tutorial
C++ Tutorial
Python Tutorial
Java Tutorial

Writing Formatted String to a File

fprintf() function 将格式化的数据流发送到由 FILE 指针表示的磁盘文件。

int fprintf(FILE *stream, const char *format [, argument, ...])

在以下程序中,我们有一个名为 " employee " 的结构类型数组。该结构有一个字符串、一个整数和一个浮点元素。使用 fprintf() 函数,将数据写入文件。

#include <stdio.h>

struct employee {
   int age;
   float percent;
   char *name;
};

int main() {

   FILE *fp;
   struct employee emp[] = {
      {25, 65.5, "Ravi"},
      {21, 75.5, "Roshan"},
      {24, 60.5, "Reena"}
   };

   char *string;
   fp = fopen("file3.txt", "w");

   for (int i = 0; i < 3; i++) {
      fprintf(fp, "%d %f %s\n", emp[i].age, emp[i].percent, emp[i].name);
   }
   fclose(fp);

   return 0;
}

Output

When the above program is executed, a text file is created with the name "file3.txt" that stores the employee data from the struct array.

Reading from a Text File

提供了以下库函数来从以读取模式打开的文件中读取数据 -

  1. fgetc() :从文件中读取单个字符。

  2. fgets() :从文件中读取字符串。

  3. fscanf() :从文件中读取格式化的字符串。

Reading Single Character from a File

fgetc() function 从由 " fp " 引用的输入文件中读取一个字符。返回值是读取的字符,或者在发生任何错误的情况下,它返回 EOF。

int fgetc(FILE * fp);

以下示例以逐个字符的方式读取给定文件,直到文件末尾。

#include <stdio.h>

int main(){

   FILE *fp ;
   char ch ;
   fp = fopen ("file1.txt", "r");

   while(1) {
      ch = fgetc (fp);
      if (ch == EOF)
         break;
      printf ("%c", ch);
   }
   printf ("\n");
   fclose (fp);
}

Output

运行代码并检查其输出:

C Programming tutorial from TutorialsPoint

Reading String from a File

fgets() function 从由 “fp” 引用的输入流中最多读取 “n - 1” 个字符。它将读取的字符串复制到缓冲区 “ buf ”,附加一个空字符以终止字符串。

下面这个程序读取给定文件中的每一行,直到检测到文件末尾−

# include <stdio.h>

int main() {

   FILE *fp;
   char *string;
   fp = fopen ("file2.txt", "r");

   while (!feof(fp)) {
      fgets(string, 256, fp);
      printf ("%s", string) ;
   }
   fclose (fp);
}

Output

运行代码并检查其输出:

C Programming Tutorial
C++ Tutorial
Python Tutorial
Java Tutorial

Reading Formatted String from a File

C 编程语言中的 fscanf() function 用于从文件中读取格式化输入。

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

在下面的程序中,我们利用 fscanf() 函数以不同类型的变量读取格式化数据。通常使用格式说明符 (%d, %f, %s 等) 来指示字段类型。

#include <stdio.h>

int main() {

   FILE *fp;
   char *s;
   int i, a;
   float p;

   fp = fopen ("file3.txt", "r");

   if (fp == NULL) {
      puts ("Cannot open file"); return 0;
   }

   while (fscanf(fp, "%d %f %s", &a, &p, s) != EOF)
   printf ("Name: %s Age: %d Percent: %f\n", s, a, p);
   fclose(fp);

   return 0;
}

Output

执行以上程序时,它将打开文本文件 “file3.txt”,并在屏幕上打印其内容。运行代码后,你将得到类似以下的输出−

Name: Ravi Age: 25 Percent: 65.500000
Name: Roshan Age: 21 Percent: 75.500000
Name: Reena Age: 24 Percent: 60.500000

File Handing Binary Read and Write Functions

在二进制文件的情况下,读/写操作以二进制形式完成。你需要在访问模式中包含字符 “ b ” (用于写入二进制文件的 “ wb ”,用于读取二进制文件的 “ rb ”)。

有两个函数可用于二进制输入和输出: fread() 函数和 fwrite() 函数。这两个函数都应用于读取或写入内存块,通常是数组或结构。

Writing to Binary File

fwrite() function 将一个指定字节块从一个缓冲区写入到以二进制写入模式打开的文件中。下面是使用此函数的原型:

fwrite(*buffer, size, no, FILE);

在下面的程序中,声明了一个名为 “ employee ” 的结构类型数组。我们使用 fwrite() 函数以一个 employee 数据大小的一个字节块写入以 “ wb ” 模式打开的文件中。

#include <stdio.h>

struct employee {
   int age;
   float percent;
   char name[10];
};

int main() {

   FILE *fp;
   struct employee e[] = {
      {25, 65.5, "Ravi"},
      {21, 75.5, "Roshan"},
      {24, 60.5, "Reena"}
   };

   char *string;

   fp = fopen("file4.dat", "wb");
   for (int i = 0; i < 3; i++) {
      fwrite(&e[i], sizeof (struct employee), 1, fp);
   }

   fclose(fp);

   return 0;
}

Output

When the above program is run, the given file will be created in the current folder. It will not show the actual data, because the file is in binary mode.

Reading from Binary File

fread() function 将一个指定字节块从以二进制读取模式打开的文件中读取到一个指定大小的缓冲区中。下面是使用此函数的原型:

fread(*buffer, size, no, FILE);

在下面的程序中,声明了一个名为 “ employee ” 的结构类型数组。我们使用 fread() 函数以一个 employee 数据大小的一个字节块读取以 “ rb ” 模式打开的文件中。

#include <stdio.h>

struct employee {
   int age;
   float percent;
   char name[10];
};

int main() {

   FILE *fp;
   struct employee e;

   fp = fopen ("file4.dat", "rb");

   if (fp == NULL) {
      puts ("Cannot open file");
      return 0;
   }

   while (fread (&e, sizeof (struct employee), 1, fp) == 1)
   printf ("Name: %s Age: %d Percent: %f\n", e.name, e.age, e.percent);

   fclose(fp);

   return 0;
}

Output

执行以上程序时,它将打开文件 “file4.dat”,并在屏幕上打印其内容。运行代码后,你将得到类似以下的输出−

Name: Ravi Age: 25 Percent: 65.500000
Name: Roshan Age: 21 Percent: 75.500000
Name: Reena Age: 24 Percent: 60.500000

Renaming a File

rename() function 用于将一个现有文件从一个旧文件名重命名为一个新文件名。

Syntax

以下是重命名文件的语法−

int rename(const char *old_filename, const char *new_filename)

Example

#include <stdio.h>

int main() {
  // old and new file names
  char * file_name1 = "file1.txt";
  char * file_name2 = "file2.txt";

  // Renaming old file name to new one
  if (rename(file_name1, file_name2) == 0) {
    printf("File renamed successfully.\n");
  } else {
    perror("There is an error.");
  }

  return 0;
}

如果存在一个文件 (file1.txt),则输出如下−

Name: Ravi Age: 25 Percent: 65.500000
Name: Roshan Age: 21 Percent: 75.500000
Name: Reena Age: 24 Percent: 60.500000