C语言文件操作的那些细节

C语言文件常用操作

一、FILE结构体

    FILE *fp = fopen("YKDog.txt", "r");

FILE 是一个结构体。文件是存放在物理磁盘上的,包括文件控制块(FCB)数据块。文件控制块通常包括文件权限、日期(创建、读取、修改)、拥有者、文件大小、数据块信息。数据块用来存储实际的内容。对于打开的文件,操作系统是这样管理的:

系统维护了两张表,一张是系统级打开文件表,一张是进程级打开文件表(每个进程有一个)

C语言文件操作的那些细节_第1张图片
FILE结构体

我们不能直接操作系统级的文件表, 所以我们可以通过进程级文件表指针间接操作FCB。FILE结构体中的_file指针指向了进程级文件表, 而进程级文件表保存了指向系统级文件表的指针和其他信息。简而言之,操作FILE结构体,就间接的操作了文件。而操作FILE结构体, 我们采用了FILE *fp这个指针。

二、fopen函数

    FILE *fp = fopen(文件路径,操作权限)

权限设置如下:

权限字符 含义
r 如果路径文件不存在就会返回NULL,不存在不会创建文件。
r+ 不存在报错并且不会创建
w 如果文件不存在不会返回NULL,并且会创建文件
a 如果文件不存在不会报错, 并且会自动创建文件
a+ 如果文件不存在不会报错自动创建, 在末尾追加不会覆盖
w+ 不存在不会返回NULL报错, 自动创建,会清空后覆盖

二、fputc和fgetc函数

fputc返回值是写入成功的字符,如果写入失败返回EOF(-1的一个宏, end of file缩写)

fputc(字符, FILE*)

fgetc(FILE*)返回一个读到的字符, 结尾或出错(比如权限不够)返回EOF
看一个练习就知道怎么用了

练习:写入a-z的字符到YKDog.txt中,再用fgetc读取

code

       
   FILE *fp = fopen("YKDog.txt", "w");
   //路径 + 写权限
   if (fp == NULL) printf("error");
   
   for(char i = 'a'; i <= 'z'; i++){
       printf("%-3c", fputc(i, fp));
       //返回值是写入成功的字符
   }
   printf("\n");

   fclose(fp);
   
   FILE *fpr = fopen("YKDog.txt", "r");
   if (fp ==  NULL) printf("error");
   char ch;
   while((ch = fgetc(fp)) != EOF){
       printf("%-3c", ch);
   }   
   

   fclose(fpr);

结果:

a  b  c  d  e  f  g  h  i  j  k  l  m  n  o  p  q  r  s  t  u  v  w  x  y  z 

a  b  c  d  e  f  g  h  i  j  k  l  m  n  o  p  q  r  s  t  u  v  w  x  y  z

要特别注意的是写完一定要fclose不然不会把缓存中的数据写到磁盘上, 导致下边的读取出问题。

返回值总结:fputc 返回值是写入成功的字符,失败返回EOF。fgetc返回值是读取到的字符,失败或结束返回EOF

三、feof判断文件流结束标识函数

函数避免使用

feof如果到结束标识就返回1, 否则返回1.

练习使用fgetc获得之前YKDog中的a-z

易错思路:
如果没有遇到结束标识就一直打印。刚好结束就不执行while中语句了。然而忽略了这个延迟, 标志位要到下一次读取(fgetc)的时候才会修改为1.下一次读取, 已经超出范围。

    FILE *fp = fopen("YKDog.txt", "r");
    if (fp == NULL) printf("error");
    
    while(!feof(fp)){

        printf("%c ", fgetc(fp));

    }

    fclose(fp);

a b c d e f g h i j k l m n o p q r s t u v w x y z ?

修改思路,既然延迟一个读写修改结束单位。那我就多读取一次

    FILE *fp = fopen("YKDog.txt", "r");
    if (fp == NULL) printf("error");

    char ch = fgetc(fp);
    while(!feof(fp)){

        printf("%c ",ch );

        ch = fgetc(fp);

    }

    fclose(fp);

四、fputs和fgets

fputs 是写一个字符串到文件中。
fpusts(字符串首地址, FILE *) 返回值是 如果写入成功返回0 或字符串的长度(平台不一样结果不一, 肯定是非负), 失败返回EOF.\n等字符也会写入。并且自动加上\0

       FILE *fp = fopen("YKPig.txt", "w");
   if(fp == NULL) printf("error");
   
   int ret=fputs("Hello, YKPig\n", fp);

   printf("ret = %d\n", ret);

有的操作系统比如centOS, MacOS会在文本编辑结束后会自动在其后加入\n也就是0a。windows不会

fgets(buf, 10, FILE *fpr)
简单的说吧, 把fpr文件内容每次10-1个字节读入到buf中。如果遇到\n或者文件结束 结束读取。每读取一次在内容后自动添加\0。

返回值是每次成功读到的 保存到buf中字符的首个地址。失败返回NULL

总结:
fgets 函数返回有三个条件:

  • 读 n-1 个字符前遇到\n,读取结束。
  • 读 n-1 个字符前遇到 EOF,读取结束。
  • 最多读 n-1 个符。
  • 在每读一行后自动加’\0’。

Mac下读内容

C语言文件操作的那些细节_第2张图片
Mac系统存储的数据

.表示\n换行。最后一个是系统加的

    FILE *fpr = fopen("YKBird.txt", "r");
    if (fpr == NULL) printf("error");
    
    char buf[1024];

    while(fgets(buf, 10, fpr) !=NULL  ){

        printf("%s=", buf);
    }

结果

123456789=abcdefg
=123456789=0
=abcdefg
=

注意:

  • 打印的时候是遇到\n才打印的。
  • buff中不是存储所有的结果。是存储每次读到的结果。
C语言文件操作的那些细节_第3张图片
小码哥iOS

你可能感兴趣的:(C语言文件操作的那些细节)