C 文件

2018-05-20 17:16 更新

学习C - C文件

C程序员使用指针来管理用于读取和写入数据的流。

流只是文件或硬件设备,如显示器或打印机。

要指向并管理C中的文件流,请使用名为FILE的数据结构。

类型FILE的指针就像任何其他变量一样创建。

#include <stdio.h> 
int main(void) { 
   //create 3 file pointers 
   FILE *pRead; 
   FILE *pWrite; 
   FILE *pAppend; 
   
   return 0;
} //end main 

上面的代码创建了三个名为pRead,pWrite和pAppend的FILE指针变量。

每个FILE指针可以打开和管理单独的数据文件。



打开和关闭文件

文件处理的基本组件是打开,处理和关闭数据文件。

打开一个文件应该有错误检查和/或处理。

未能测试文件打开的结果将导致不必要的程序结果。

要打开数据文件,请使用标准输入/输出库函数fopen()。

fopen()函数返回一个指向FILE指针的FILE指针。


#include <stdio.h> 
main() 
{ 
   FILE *pRead; 
   pRead = fopen("file1.dat", "r"); 
} //end main  

该程序使用fopen()函数以只读方式打开名为file1.dat的数据文件。

fopen()函数返回一个FILE指针返回到pRead变量。

fopen()函数有两个参数:文件名,第二个参数告诉fopen()如何打开文件。

下表列出了使用fopen()打开文本文件的几个常用选项。

模式描述
r打开文件进行阅读
w创建写入文件; 丢弃任何以前的数据
a写入文件结尾(追加)

上面的代码生成以下结果。



打开文件示例

打开文件后,应确保文件指针成功返回。

要测试fopen()的返回值,请测试条件中的NULL值,如下所示。


#include <stdio.h> 
main() 
{ 
   FILE *pRead; 
   pRead = fopen("file1.dat", "r"); 
   if ( pRead == NULL ) 
      printf("\nFile cannot be opened\n"); 
   else 
      printf("\nFile opened for reading\n"); 
} //end main 

以下条件

if ( pRead == NULL )

可以缩短下一个条件。

if ( pRead ) 

如果pRead返回非NULL,则if条件为true。如果pRead返回NULL,则该条件为false。

成功打开和处理文件后,应使用函数fclose()关闭文件。

fclose()函数使用FILE指针来刷新流并关闭文件。

fclose()函数将FILE指针名称作为参数。

fclose(pRead);

上面的代码生成以下结果。

读取数据

以下代码显示如何使用函数fscanf()和feof()读取文件的内容并检查文件的EOF(文件结尾)标记。

以下程序读取名为.dat的数据文件,直到读取文件结束标记为止。


#include <stdio.h> 
main() 
{ 
   FILE *pRead; 
   char name[10]; 
   pRead = fopen("names.dat", "r"); 
   if ( pRead == NULL ) 
      printf("\nFile cannot be opened\n"); 
   else 
      printf("\nContents of names.dat\n\n"); 
   fscanf(pRead, "%s", name); 
   while ( !feof(pRead) ) { 
         printf("%s\n", name); 
         fscanf(pRead, "%s", name); 
   }  //end loop 
} //end main 

在成功打开names.dat之后,我使用fscanf()函数来读取文件中的一个字段。

fscanf()函数与scanf()函数类似,但与FILE流有关。

它有三个参数:一个FILE指针,一个数据类型和一个变量来存储检索到的值。

读取记录后,printf()函数显示文件中的数据。

要读取多个记录,请使用可以读取所有记录的循环,直到满足条件。

要读取所有记录,直到满足文件结尾,请使用feof()函数。

使用非运算符(!),可以将FILE指针传递给feof()函数并循环,直到达到文件结尾标记时函数返回非零值。

通过向第二个参数提供记录中每个字段的一系列类型说明符,fscanf()也可以读取包含多个字段的记录。

例如,下一个fscanf()函数希望读取两个名为name和hobby的字符串。

fscanf(pRead, "%s%s", name, hobby);

%s类型说明符将读取一系列字符,直到找到空白,包括空白,新行或选项卡。

fscanf()函数的其他有效类型说明符列在表11.3中。

类型描述
c单字符
d十进制整数
e,E,f,g,G浮点
o八进制整数
s字符串
u无符号十进制整数
x,X十六进制整数

上面的代码生成以下结果。

多个字段示例

以下代码显示如何读取多个字段。


#include <stdio.h> 
main() 
{ 
   FILE *pRead; 
   char name[10]; 
   char hobby[15]; 
   pRead = fopen("hobbies.dat", "r"); 
   if ( pRead == NULL ) 
      printf("\nFile cannot be opened\n"); 
   else 
      printf("\nName\tHobby\n\n"); 

   fscanf(pRead, "%s%s", name, hobby); 
   while ( !feof(pRead) ) { 
         printf("%s\t%s\n", name, hobby); 
         fscanf(pRead, "%s%s", name, hobby); 
   }  //end loop 
} //end main 

上面的代码生成以下结果。

写数据

fprintf()函数接收FILE指针,数据类型列表以及将数据写入数据文件的值列表。

例子

通过用记录分隔记录中的每个字段,我可以使用以下程序轻松地读取相同的记录。


#include <stdio.h> 
main() 
{ 
   FILE *pRead; 
   char fName[20]; 
   char lName[20]; 
   char id[15]; 
   float gpa; 
   pRead = fopen("students.dat", "r"); 
   if ( pRead == NULL ) 
      printf("\nFile not opened\n"); 
   else { 
      //print heading 
      printf("\nName\t\tID\t\tGPA\n\n"); 
      //read field information from data file and store in variables 
      fscanf(pRead, "%s%s%s%f", fName, lName, id, &gpa); 
      //print variable data to standard output 
      printf("%s %s\t%s\t%.2f\n", fName, lName, id, gpa); 
      fclose(pRead); 
   }  //end if 
} //end main  

使用带有w参数值的fopen()打开数据文件将会擦除文件中存储的任何以前的数据。

使用a属性在文件末尾附加数据。

上面的代码生成以下结果。

附加数据

将信息附加到数据文件中,包括使用fopen()中的一个属性打开一个写入文件,并将数据写入现有文件的末尾。

但是,如果该文件不存在,则会按照fopen()语句中的指定创建一个新的数据文件。

以下代码演示将记录附加到现有数据文件。

#include <stdio.h> 
void readData(void); 
main() 
{ 
   FILE *pWrite; 
   char name[10]; 
   char hobby[15]; 
   printf("\nCurrent file contents:\n"); 
   readData(); 
   printf("\nEnter a new name and hobby: "); 
   scanf("%s%s", name, hobby); 
   //open data file for append 
   pWrite = fopen("hobbies.dat", "a"); 
   if ( pWrite == NULL ) 
      printf("\nFile cannot be opened\n"); 
   else { 
      //append record information to data file 
      fprintf(pWrite, "%s %s\n", name, hobby); 
      fclose(pWrite); 
      readData(); 
   }  //end if 
} //end main 

void readData(void) 
{ 
   FILE *pRead; 
   char name[10]; 
   char hobby[15]; 
   //open data file for read access only 
   pRead = fopen("hobbies.dat", "r"); 
   if ( pRead == NULL ) 
      printf("\nFile cannot be opened\n"); 
   else { 
      printf("\nName\tHobby\n\n"); 
      fscanf(pRead, "%s%s", name, hobby); 
      //read records from data file until end of file is reached 
      while ( !feof(pRead) ) { 
         printf("%s\t%s\n", name, hobby); 
         fscanf(pRead, "%s%s", name, hobby); 
      } 
   }
   fclose(pRead); 
} //end readData 

上面的代码生成以下结果。

例2

以下代码使用goto和一些新功能(perror()和exit())来构建文件I/O程序中的错误处理。


#include <stdio.h> 
#include <stdlib.h> 
main() { 
   FILE *pRead; 
   char name[10]; 
   char hobby[15]; 
   pRead = fopen("hobbies.dat", "r"); 
   if ( pRead == NULL ) 
      goto ErrorHandler; 
   else { 
      printf("\nName\tHobby\n\n"); 
      fscanf(pRead, "%s%s", name, hobby); 
      while ( !feof(pRead) ) { 
         printf("%s\t%s\n", name, hobby); 
         fscanf(pRead, "%s%s", name, hobby); 
      }  //end loop 
   } // end if 
   exit(EXIT_SUCCESS); //exit program normally 
   ErrorHandler: 
        perror("The following error occurred"); 
        exit(EXIT_FAILURE); //exit program with error 

} //end main 

exit()函数(<stdlib.h>库的一部分)终止程序,就好像它正常退出一样。

如下所示,exit()函数对于想要在遇到文件I/O(输入/输出)错误时终止程序的程序员很常见。

exit(EXIT_SUCCESS); //exit program normally


exit(EXIT_FAILURE); //exit program with error 

exit()函数接受一个参数,一个常量为EXIT_SUCCESS或EXIT_FAILURE,两者都分别为成功或失败返回预定义的值。

perror()函数向标准输出发送消息,描述遇到的最后一个错误。

perror()函数采用单个字符串参数,首先打印,后跟冒号和空白,然后系统生成错误消息和新行。

perror("The following error occurred");

上面的代码生成以下结果。

以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号