📜  C文件处理

📅  最后修改于: 2020-10-04 12:13:28             🧑  作者: Mango

在本教程中,您将学习C语言中的文件处理。您将学习在f的帮助下使用fprintf(),fscanf(),fread(),fwrite(),fseek()等在C中处理标准I / O。例子。

文件是计算机存储设备中用于存储数据的容器。


为什么需要文件?
  • 当程序终止时,所有数据都会丢失。即使程序终止,存储在文件中也会保留您的数据。
  • 如果必须输入大量数据,则将花费大量时间来全部输入。
    但是,如果您有一个包含所有数据的文件,则可以使用C中的一些命令轻松地访问文件的内容。
  • 您可以轻松地将数据从一台计算机移动到另一台计算机,而无需进行任何更改。

文件类型

处理文件时,应了解两种类型的文件:

  1. 文字档
  2. 二进制文件

1.文本文件

文本文件是普通的.txt文件。您可以使用任何简单的文本编辑器(例如记事本)轻松创建文本文件。

打开这些文件时,您将以纯文本形式看到文件中的所有内容。您可以轻松地编辑或删除内容。

它们以最少的维护工作,易于阅读,提供最少的安全性并占用更大的存储空间。

2.二进制文件

二进制文件主要是计算机中的.bin文件。

它们不是以纯文本格式存储数据,而是以二进制格式(0和1)存储数据。

与文本文件相比,它们可以容纳更多数据,不易读取,并提供更好的安全性。


文件操作

在C中,您可以对文件执行四个主要操作,即文本或二进制:

  1. 创建一个新文件
  2. 打开现有文件
  3. 关闭档案
  4. 读取信息并将信息写入文件

处理文件

处理文件时,需要声明文件类型的指针。文件和程序之间的通信需要此声明。

FILE *fptr;

打开文件-用于创建和编辑

使用stdio.h头文件中定义的fopen() 函数执行fopen()文件。

在标准I / O中打开文件的语法为:

ptr = fopen("fileopen","mode");

例如,

fopen("E:\\cprogram\\newprogram.txt","w");

fopen("E:\\cprogram\\oldprogram.bin","rb");
  • 假设文件newprogram.txtE:\cprogram位置不存在。第一个函数创建一个名为newprogram.txt的新文件,并按照‘w’模式打开该文件进行写入。
    写入模式允许您创建和编辑(覆盖)文件的内容。
  • 现在,我们假设第二个二进制文件oldprogram.bin位于E:\cprogram位置。第二个函数打开现有文件,以二进制模式‘rb’读取。
    读取模式仅允许您读取文件,而不能写入文件。
Opening Modes in Standard I/O
Mode Meaning of Mode During Inexistence of file
r Open for reading. If the file does not exist, fopen() returns NULL.
rb Open for reading in binary mode. If the file does not exist, fopen() returns NULL.
w Open for writing. If the file exists, its contents are overwritten.
If the file does not exist, it will be created.
wb Open for writing in binary mode. If the file exists, its contents are overwritten.
If the file does not exist, it will be created.
a Open for append.
Data is added to the end of the file.
If the file does not exist, it will be created.
ab Open for append in binary mode.
Data is added to the end of the file.
If the file does not exist, it will be created.
r+ Open for both reading and writing. If the file does not exist, fopen() returns NULL.
rb+ Open for both reading and writing in binary mode. If the file does not exist, fopen() returns NULL.
w+ Open for both reading and writing. If the file exists, its contents are overwritten.
If the file does not exist, it will be created.
wb+ Open for both reading and writing in binary mode. If the file exists, its contents are overwritten.
If the file does not exist, it will be created.
a+ Open for both reading and appending. If the file does not exist, it will be created.
ab+ Open for both reading and appending in binary mode. If the file does not exist, it will be created.

关闭档案

读取/写入后,应关闭文件(文本文件和二进制文件)。

使用fclose() 函数执行关闭文件。

fclose(fptr);

在这里, fptr是与要关闭的文件关联的文件指针。


读取和写入文本文件

为了读取和写入文本文件,我们使用函数fprintf()fscanf().

它们只是printf()scanf()的文件版本。唯一的区别是fprint()fscanf()需要指向结构FILE的指针。


示例1:写入文本文件

#include 
#include 

int main()
{
   int num;
   FILE *fptr;

   // use appropriate location if you are using MacOS or Linux
   fptr = fopen("C:\\program.txt","w");

   if(fptr == NULL)
   {
      printf("Error!");   
      exit(1);             
   }

   printf("Enter num: ");
   scanf("%d",&num);

   fprintf(fptr,"%d",num);
   fclose(fptr);

   return 0;
}

该程序从用户那里获取一个号码,并将其存储在文件program.txt

编译并运行该程序后,您会看到在计算机的C驱动器中创建的文本文件program.txt 。打开文件时,您可以看到输入的整数。


示例2:从文本文件读取

#include 
#include 

int main()
{
   int num;
   FILE *fptr;

   if ((fptr = fopen("C:\\program.txt","r")) == NULL){
       printf("Error! opening file");

       // Program exits if the file pointer returns NULL.
       exit(1);
   }

   fscanf(fptr,"%d", &num);

   printf("Value of n=%d", num);
   fclose(fptr); 
  
   return 0;
}

该程序读取program.txt文件中存在的整数并将其打印到屏幕上。

如果您从示例1成功创建了文件,运行此程序将为您提供输入的整数。

其他功能,如fgetchar()fputc()等,也可以类似的方式使用。


读写二进制文件

在二进制文件的情况下,函数fread()fwrite()分别用于读取和写入磁盘上的文件。


写入二进制文件

要写入二进制文件,需要使用fwrite() 函数。这些函数采用四个参数:

  1. 要写入磁盘的数据地址
  2. 要写入磁盘的数据大小
  3. 此类数据的数量
  4. 指向要写入的文件的指针。
fwrite(addressData, sizeData, numbersData, pointerToFile);

示例3:使用fwrite()写入二进制文件

#include 
#include 

struct threeNum
{
   int n1, n2, n3;
};

int main()
{
   int n;
   struct threeNum num;
   FILE *fptr;

   if ((fptr = fopen("C:\\program.bin","wb")) == NULL){
       printf("Error! opening file");

       // Program exits if the file pointer returns NULL.
       exit(1);
   }

   for(n = 1; n < 5; ++n)
   {
      num.n1 = n;
      num.n2 = 5*n;
      num.n3 = 5*n + 1;
      fwrite(&num, sizeof(struct threeNum), 1, fptr); 
   }
   fclose(fptr); 
  
   return 0;
}

在此程序中,我们在C驱动器中创建一个新文件program.bin

我们声明一个具有三个数字n1,n2和n3的结构threeNum ,并在主函数中将其定义为num。

现在,在for循环内,我们使用fwrite()将值存储到文件中。

第一个参数使用num的地址,第二个参数使用结构threeNum的大小。

由于我们仅插入num的一个实例,因此第三个参数是1 。并且,最后一个参数*fptr指向我们正在存储数据的文件。

最后,我们关闭文件。


从二进制文件读取

函数fread()也采用4个参数,类似于上面的fwrite() 函数 。

fread(addressData, sizeData, numbersData, pointerToFile);

示例4:使用fread()从二进制文件读取

#include 
#include 

struct threeNum
{
   int n1, n2, n3;
};

int main()
{
   int n;
   struct threeNum num;
   FILE *fptr;

   if ((fptr = fopen("C:\\program.bin","rb")) == NULL){
       printf("Error! opening file");

       // Program exits if the file pointer returns NULL.
       exit(1);
   }

   for(n = 1; n < 5; ++n)
   {
      fread(&num, sizeof(struct threeNum), 1, fptr); 
      printf("n1: %d\tn2: %d\tn3: %d", num.n1, num.n2, num.n3);
   }
   fclose(fptr); 
  
   return 0;
}

在此程序中,您读取相同的文件program.bin并逐个循环浏览记录。

简单来说,你读一个threeNum的记录threeNum大小从文件中指出由* FPTR到结构NUM。

您将获得与示例3中插入的记录相同的记录。


使用fseek()获取数据

如果文件中有许多记录,并且需要访问特定位置的记录,则需要遍历所有记录才能获取该记录。

这将浪费大量的内存和操作时间。使用fseek()可以更轻松地获取所需数据。

顾名思义, fseek()光标搜索到文件中的给定记录。


fseek()的语法

fseek(FILE * stream, long int offset, int whence);

第一个参数流是指向文件的指针。第二个参数是要查找的记录的位置,第三个参数指定偏移量开始的位置。

Different whence in fseek()
Whence Meaning
SEEK_SET Starts the offset from the beginning of the file.
SEEK_END Starts the offset from the end of the file.
SEEK_CUR Starts the offset from the current location of the cursor in the file.

示例5:fseek()

#include 
#include 

struct threeNum
{
   int n1, n2, n3;
};

int main()
{
   int n;
   struct threeNum num;
   FILE *fptr;

   if ((fptr = fopen("C:\\program.bin","rb")) == NULL){
       printf("Error! opening file");

       // Program exits if the file pointer returns NULL.
       exit(1);
   }
   
   // Moves the cursor to the end of the file
   fseek(fptr, -sizeof(struct threeNum), SEEK_END);

   for(n = 1; n < 5; ++n)
   {
      fread(&num, sizeof(struct threeNum), 1, fptr); 
      printf("n1: %d\tn2: %d\tn3: %d\n", num.n1, num.n2, num.n3);
      fseek(fptr, -2*sizeof(struct threeNum), SEEK_CUR);
   }
   fclose(fptr); 
  
   return 0;
}

该程序将以相反的顺序(从最后到第一)开始从文件program.bin中读取记录并进行打印。