C语言学习之路--第十三站 文件读写

127 阅读4分钟

上一部分处理了标准输入与输出设备,这部分学习创建、打开、关闭文本文件或二进制文件。

C语言提供了访问顶层的函数,也提供了底层(OS)调用来处理存储设备上的文件。

打开文件

可以使用fopen() 函数来创建一个新的文件或打开一个已有的文件。函数会调用初始化类型 FILE 的一个对象,类型 FILE 包含了所有用来控制流的必要信息。函数原型:FILE *fopen( const char *filename , const char *mode);

  • filename 是字符串,用来命名文件
  • 访问模式 mode ,处理文本文件:
    • r | 打开一个已有文件,允许读写
    • w | 打开一个文本文件,允许写入。如果不存在就创建一个,从开头写入内容。如果存在就截断为零长度,重新写入
    • a | 打开一个文本文件,追加写入。如果不存在创建,存在追加
    • r+ | 打开一个文件,允许读写
    • w+ | 打开一个文件,允许读写。如果存在截断为零长度,不存在创建
    • a+ | 打开一个文件,允许读写。如果不存在创建。读取会从文件的开头开始,写入只能是追加
  • 处理二进制文件
    • "rb", "wb", "ab", "rb+", "r+b", "wb+", "w+b", "ab+", "a+b"

关闭文件

  • 使用 fclose() 函数
  • int fclose( FILE *fp);
  • 如果成功关闭,fclose()返回零。如果错误返回 EOF
  • 函数会清空缓冲区中的数据,关闭文件,并释放用于该文件的所有内存。EOF是一个定义在头文件 stdion.h 中的常量

写入文件

  • 把字符写入流中最简单的函数时 fputc()
    • int fputc( int c , FILE *fp);
      • 将参数c的字符写入到fp所指向的输出流中。如果写入成功会返回写入的字符,错误会返回 EOF。
    • ` int fputc( const char *s , FILE *fp);
      • 将字符串s写入到fp所指向的输出流中。写入成功返回一个非负值,错误返回 EOF。
  • 也可以使用 fprintf()函数写入一个字符串
    • int fprintf(FILE *fp , const char *format, .... )

读取文件

  • 读取单个字符最简单的函数 fgetc()
    • int fgetc( FILE * fp);
    • 读取一个字符,返回值为读取的字符,错误返回 EOF
  • 从流中读取一个字符串
    • `char *fgets(char *buf , int n , FILE *fp);
    • 从fp指向的输入流中读取 n-1 个字符。读取到的复制到缓冲区 buf ,最后追加一个 null 字符。
    • 如果在读取最后一个字符之前遇到换行符 "\n" 或者文件的末尾 EOF ,只返回读取到的字符,包括换行符
  • 从流中读取字符串,遇到空格换行停止
    • int fscanf(FILE *fp , const char *format,...)
    • 与 fgets 相同,但是遇到第一个空格和换行符时,停止读取

二进制 I/O 函数

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

下面写一个方法实践一下:

int file_demo()
{
FILE *fp = NULL;
fopen_s(&fp,"tmp/C_test.txt", "w+");

fprintf(fp, "hellp world.\n");
int tes = fputs("the word is hellp;\n",fp);
printf("%d\n", tes);
int ted = fprintf(fp, "hahah,three demo.\n");
printf("%d\n", ted);
int s = 1389;
int tef = fputc(s, fp);
printf("%d\n", tef);
fclose(fp);
}

image.png

image.png

有几个问题需要注意:

  • fopen提示不安全,根据提示可以在开头添加常量忽略不安全提醒,但是失败。改用fopen_s ,文件要求二次指针,因此fp前加&
  • fputs 把字符串写入fp指定的流,返回的是非负值
  • fputc 把参数c的字符值写入到fp指定流中,写入成功返回写入的字符

下面将方法进行扩充

FILE* rd = NULL;
char buff[255] ;
char buff2[255];
char buff3[255];
fopen_s(&rd, "tmp/C_test.txt", "r");

fscanf_s(rd, " %s ",buff , 20);
printf("读取rd的内容:%s |\n", buff);

//fgetc(rd);
//printf("读取rd内容:%s |\n", buff1);

fgets(buff2, 255, (FILE*)rd);
printf("读取rd内容:%s |\n", buff2);
fgets(buff3, 255, (FILE*)rd);
printf("读取rd内容:%s |\n", buff3);

fclose(rd);
  • 主要添加了读取的操作
  • 需要注意的是fscanf 需要添加_s 在使用时候需要添加内存大小image.png 防止内存溢出
  • 还有一点就是fgetc的使用没有涉及到,也没有找到很对应的测试,暂时搁置。

image.png

还有就是 二进制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);

主要用于存储块的读写,通常是数组或结构体