C 语言编程教程

C 语言 - 首页

C 语言基础

C 语言 - 概述 C 语言 - 特性 C 语言 - 发展历史 C 语言 - 环境设置 C 语言 - 程序结构 C 语言 - Hello World C - 编译过程 C - 注释 C - 标记 C - 关键字 C - 标识符 C - 用户输入 C - 基本语法 C - 数据类型 C - 变量 C - 整数提升 C - 类型转换 C - 类型转换 C - 布尔值

C 语言中的常量和文字

C - 常量 C - 字面量 C - 转义序列 C - 格式说明符

C 语言中的运算符

C - 运算符 C - 算术运算符 C - 关系运算符 C - 逻辑运算符 C - 位运算符 C - 赋值运算符 C - 一元运算符 C - 递增和递减运算符 C - 三元运算符 C - sizeof 运算符 C - 运算符优先级 C - 其他运算符

C 语言中的决策

C - 决策 C - if 语句 C - if...else 语句 C - 嵌套 if 语句 C - switch 语句 C - 嵌套 switch 语句

C 语言中的循环

C - 循环 C - While 循环 C - For 循环 C - Do...while 循环 C - 嵌套循环 C - 无限循环 C - Break 语句 C - Continue 语句 C - goto 语句

C 语言中的函数

C - 函数 C - Main 函数 C - 按值调用函数 C - 按引用调用函数 C - 嵌套函数 C - 可变参数函数 C - 用户定义函数 C - 回调函数 C - return 语句 C - 递归

C 语言中的作用域规则

C - 作用域规则 C - 静态变量 C - 全局变量

C 语言中的数组

C - 数组 C - 数组的属性 C - 多维数组 C - 将数组传递给函数 C - 从函数返回数组 C - 可变长度数组

C 语言中的指针

C - 指针 C - 指针和数组 C - 指针的应用 C - 指针运算 C - 指针数组 C - 指向指针的指针 C - 将指针传递给函数 C - 从函数返回指针 C - 函数指针 C - 指向数组的指针 C - 指向结构体的指针 C - 指针链 C - 指针 vs 数组 C - 字符指针和函数 C - NULL 指针 C - void 指针 C - 悬垂指针 C - 解引用指针 C - Near、Far 和 Huge 指针 C - 指针数组的初始化 C - 指针与多维数组

C 语言中的字符串

C - 字符串 C - 字符串数组 C - 特殊字符

C 语言的结构体和联合

C - 结构体 C - 结构体和函数 C - 结构体数组 C - 自引用结构 C - 查找表 C - 点 (.) 运算符 C - 枚举(或 enum) C - 结构填充和打包 C - 嵌套结构 C - 匿名结构和联合 C - 联合 C - Bit 位字段 C - Typedef

C 语言中的文件处理

C - 输入和输出 C - 文件 I/O(文件处理)

C 语言中的预处理器

C - 预处理器 C - #pragma 编译指示 C - 预处理器操作符 C - 宏 C - 头文件

C 语言中的内存管理

C - 内存管理 C - 内存地址 C - 存储类

C 其他主题

C - 错误处理 C - 可变参数 C - 命令执行 C - 数学函数 C - static 静态关键字 C - 随机数生成 C - 命令行参数

C 语言编程资源

C语言问题与解答答案 C语言快速指南 C语言速查表 C语言实用资源 C语言讨论


C 语言文件处理

C 语言文件处理

C 语言文件处理是指使用 C 语言函数执行文件操作(例如创建、打开、写入数据、读取数据、重命名和删除)的过程。借助这些函数,我们可以在程序中执行文件操作,在文件中存储和检索数据。

C 语言文件处理的必要性

如果我们使用 C 语言程序执行输入和输出操作,则只要程序运行,数据就会存在;程序终止后,我们就无法再次使用该数据。文件处理用于处理存储在外部存储器中的文件,即在计算机的外部存储器中存储和访问信息。您可以使用文件处理永久保存数据。

文件类型

文件表示一个字节序列。文件有两种类型:文本文件二进制文件 -

  1. 文本文件 - 文本文件以 ASCII 字符的形式包含数据,通常用于存储字符流。文本文件中的每一行都以换行符(" ")结尾,并且通常以".txt"为扩展名。
  2. 二进制文件 - 二进制文件以原始位(0 和 1)的形式包含数据。不同的应用程序对位和字节的表示方式不同,并使用不同的文件格式。图像文件(.png、.jpg)、可执行文件(.exe、.com)等都是二进制文件的示例。

FILE 指针 (File*)

使用文件处理时,需要一个文件指针来存储 fopen() 函数返回的 FILE 结构的引用。所有文件处理操作都需要该文件指针。

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

typedef struct {
    int fd; 			/* 文件描述符 */
    unsigned char *buf; /* 缓冲区 */
    size_t size; 		/* 文件大小 */
    size_t pos; 		/* 文件中的当前位置 */
} FILE;

声明文件指针 (FILE*)

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

FILE* file_pointer;

打开(创建)文件

任何操作都必须打开文件。fopen() 函数用于创建新文件或打开现有文件。您需要指定要打开的模式。下文介绍了各种文件打开模式,创建/打开文件时可以使用其中任何一种。

fopen() 函数返回一个 FILE 指针,该指针可用于其他操作,例如读取、写入和关闭文件。

语法

以下是打开文件的语法 -

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

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

文件打开模式

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

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

文件可以使用多种模式打开。以下是不同的文件打开模式 -

模式 描述
r 打开现有文本文件进行读取。
w 打开文本文件进行写入。如果文件不存在,则创建一个新文件。此处,程序将从文件开头开始写入内容。
a 以追加模式打开一个文本文件进行写入。如果文件不存在,则创建一个新文件。此处,程序将开始在现有文件内容中追加内容。
r+ 打开一个文本文件进行读写操作。
打开一个文本文件进行读写操作。如果文件存在,则首先将其长度截断为零;如果文件不存在,则创建一个文件。
a+ 打开一个文本文件进行读写操作。如果文件不存在,则创建该文件。读取操作将从头开始,但写入操作只能追加。

创建文件示例

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

#include <stdio.h>

int main() {
    FILE * file;
    
    // 创建文件
    file = fopen("file1.txt", "w");
    
    // 检查文件是否已创建
  if (file == NULL) {
    printf("Error in creating file");
    return 1;
  }
  printf("File created.");

  return 0;
}

输出

File created.

打开文件示例

以下示例中,我们将打开一个现有文件。打开现有文件的文件模式为"r"(只读)。您也可以使用上面介绍的其他文件打开模式选项。

注意:必须有一个要打开的文件。

#include <stdio.h>

int main() {
    FILE * file;
    
    // 打开文件
    file = fopen("file1.txt", "r");
    
    // 检查文件是否已打开
    if (file == NULL) {
        printf("Error in opening file");
        return 1;
    }
    printf("File opened.");
    
    return 0;
}

输出

File opened.

关闭文件

每个文件在执行操作后都必须关闭。fclose() 函数 用于关闭已打开的文件。

语法

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

int fclose(FILE *fp);

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

fclose() 函数实际上会将缓冲区中所有待处理的数据刷新到文件中,关闭文件并释放文件占用的内存。 EOF 是头文件 stdio.h 中定义的常量。

关闭文件示例

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

#include <stdio.h>

int main() {
  FILE * file;

    // 打开文件
    file = fopen("file1.txt", "w");
    
    // 检查文件是否已打开
    // 是否已打开
    if (file == NULL) {
        printf("Error in opening file");
        return 1;
    }
    printf("File opened.");
    
    // 关闭文件
    fclose(file);
  printf("
File closed.");

  return 0;
}

输出

File opened.
File closed.

写入文本文件

以下库函数用于将数据写入以可写模式打开的文件中 -

  • fputc():将单个字符写入文件。
  • fputs():将字符串写入文件。
  • fprintf():将格式化的字符串(数据)写入文件。

将单个字符写入文件

fputc() 函数是一个非格式化函数,它将参数"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 ("
");
   fclose(fp);
   
   return 0;
}

输出

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

将字符串写入文件

fputs() 函数将字符串"s"写入"fp"引用的输出流。成功时返回非负值,否则返回 EOF(文件尾)。

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

示例

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

#include <stdio.h>

int main() {

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

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

   fclose(fp);
   
   return 0;
}

输出

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

C Programming Tutorial
C++ Tutorial
Python Tutorial
Java Tutorial

将格式化字符串写入文件

fprintf() 函数将格式化的数据流发送到 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
", emp[i].age, emp[i].percent, emp[i].name);
   }
   fclose(fp);
   
   return 0;
}

输出

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.

从文本文件读取

以下库函数可用于从以读取模式打开的文件中读取数据 -

  • fgetc():从文件中读取单个字符。
  • fgets():从文件中读取字符串。
  • fscanf():从文件中读取格式化字符串。

从文件中读取单个字符

fgetc() 函数从"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 ("
");
   fclose (fp);
}

输出

运行代码并检查其输出 −

C Programming tutorial from TutorialsPoint

从文件读取字符串

fgets() 函数从"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);
}

输出

运行代码并检查其输出 −

C Programming Tutorial
C++ Tutorial
Python Tutorial
Java Tutorial

从文件读取格式化字符串

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

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
", s, a, p);
   fclose(fp);

   return 0;
}

输出

上述程序执行后,会打开文本文件"file3.txt",并将其内容打印在屏幕上。运行代码后,您将获得如下输出:

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

文件处理二进制读写函数

对于二进制文件,读写操作以二进制形式进行。您需要在访问模式中包含字符"b"(写入二进制文件时使用"wb",读取二进制文件时使用"rb")。

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

写入二进制文件

fwrite() 函数将指定的字节块从缓冲区写入以二进制写入模式打开的文件。以下是该函数的原型:

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;
}

输出

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.

读取二进制文件

fread() 函数 从以二进制读取模式打开的文件中读取指定大小的字节块,并将其保存到指定大小的缓冲区中。以下是该函数的原型:

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

示例

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

#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
", e.name, e.age, e.percent);

   fclose(fp);
   
   return 0;
}

输出

上述程序执行后,会打开文件"file4.dat",并将其内容打印在屏幕上。运行代码后,您将获得如下输出:

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

重命名文件

rename() 函数用于将现有文件从旧文件名重命名为新文件名。

语法

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

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

示例

#include <stdio.h>

int main() {
    // 旧文件名和新文件名
    char * file_name1 = "file1.txt";
    char * file_name2 = "file2.txt";
    
    // 将旧文件名重命名为新文件名
  if (rename(file_name1, file_name2) == 0) {
    printf("File renamed successfully.
");
  } 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