C语言笔记:C语言的文件操作

C语言的文件操作的理论

  • 数据流
  • 缓冲区buffer
    stdio.h头文件里的文件操作是带缓冲区的,也就是在内存里开辟出一块空间,程序的各个操作是先和内存进行交互,在交互完成、缓冲区满了、flush或close后,才会从缓冲区导入到磁盘中,因为内存的读取速度是远远大于磁盘的。

函数1 FILE * fopen(const char * url,const char* mode)

  • 说明:fopen函数用于打开文件流
  • 参数:
    • 字符串类型–>文件的路径
      文件的路径记得要加入转义字符。
    • 字符串类型–>对这个文件的处理方式
      处理方式有:
      r–>只读,且文件必须存在
      w–>创建一个用于写入的空文件。如果文件名称与已存在的文件相同,则会删除已有文件的内容, 文件被视为一个新的空文件。
      a 追加到一个文件。写操作向文件末尾追加数据。如果文件不存在,则创建文件。
      r+ 打开一个用于更新的文件,可读取也可写入。该文件必须存在。
      w+创建一个用于读写的空文件。
      a+ 打开一个用于读取和追加的文件。
  • 返回值:
    • 文件存在,返回文件指针FILE
    • 文件不存在,返回NULL
	FILE *fp;
	//注意路径里的转义字符
	fp = fopen("C:\\Users\\41061\\Desktop\\cfile.txt","r+");
	
	if(fp == NULL){
    
    
		printf("文件不存在");
		return 0; 
	}else{
    
    
		printf("已经打开了文件\n");
	}

函数2 int fclose(FILE *stream)

  • 说明:fclose用于关闭文件流
  • 参数:
    • FILE指针–>需要关闭的文件流
  • 返回值:
    • 流成功关闭,则该方法返回零
    • 失败,则返回 EOF。

函数3 int fgetc(FILE *stream)

  • 说明: fgetc 获取流中光标当前位置后的一个字符,他的返回值是int类型,读取到的字符char会强转为int。
  • 参数:
    • FILE指针–>要读取的流
  • 返回值:
    • 读取成功 返回字符(int类型)
    • 到达文件末尾或发生读错误,返回 EOF
	/*这里成功读取了字符 注意fgetc的返回值是int*/
	int c;
	//判断是否到了文件尾
	while( (c = fgetc(fp)) != EOF ){
    
    
		printf("%c",c); 
	} 
	printf("\n文件内容输出完毕\n"); 

函数4 int fputc(FILE *stream)

  • 说明:fputc 向流里写入一个字符,具体写在哪里,是开头 ,还是光标的位置,还是追加,seek里另说。这里在测试的时候出现了一个问题,文件里有若干个字符,我用fgetc读取一个后,再使用fputc追加模式,就无法追加了。
  • 参数:
    • FILE指针–>要读取的流
  • 返回值:
    • 写入成功 返回写入的字符(int类型)
    • 发生错误,返回 EOF
	int c;
	while( (c = getchar()) != '\n'){
    
    
		fputc(c,fp); 
		printf("写入了%c\n",c); 
	} 
 	printf("\n文件写入完毕"); 
    //这种情况下使用a+模式  ,无法追加。
	printf("%c",fgetc(fp));
	/*fputc是写入字符*/
	int c;
	while( (c = getchar()) != '\n'){
    
    
		fputc(c,fp); 
		printf("写入了%c\n",c); 
	} 
 	printf("\n文件写入完毕"); 

函数5 char *fgets(char *str, int n, FILE *stream)

  • 说明:函数的作用是在流中读取,返回一个字符串指针。
  • 参数:
    • 字符串指针–>指向读取好的字符串
    • 整型–>指定读取的长度 比如5,实际上读取4个,最后一个是空。 “ABCDE” 读取5个,返回的是ABCD 。
    • FILE文件流
  • 返回值:它的返回值和第一个参数是一样的。如果读取失败会返回空指针。
    //这里一定要初始化一下,不能仅仅定义一个指针,就算要定义指针,也要为指针初始化。
 	char str[1024];
	fgets(str,1024,fp); 
 	printf("使用fgets读取到的字符串:%s",str);

函数6 int fputs(const char *str, FILE *stream)

  • 说明:函数的作用是往流中输入一串字符串。
  • 参数:
    • 字符串–>输入的字符串
    • 文件流
  • 返回值: 它的返回值是一个int类型,该函数返回一个非负值,如果发生错误则返回 EOF。
	char str[1024];
	//stdin是键盘的标准输入
	if(fputs(fgets(str,5,stdin),fp) != EOF)
		printf("输入成功%s",str);
	else
		printf("输入失败");

函数7 int fprintf(FILE *stream, const char *format, …)

  • 说明:printf是把内容输出到终端显示器上,就会显示出来,而fprintf是输出到文件里,在文件中显示。print原意为打印,输出。所谓输入输出,都是相对于程序而且,从程序到文件,就是输出。
  • 参数:参数很多,总的分为3块。
    • 格式 %d %c %s这些
    • 内容 就是格式里的%d %c %s 的内容
  • 返回值:如果成功,则返回写入的字符总数,否则返回一个负数。
 	char str1[] = "hello";
 	char str2[] = "world";
	int num = fprintf(fp,"%s %s",str1,str2); 
	//返回值是11 因为有一个空格
	printf("%d",num);

函数8 int fscanf(FILE *stream, const char *format, …)

  • 说明:这是标准输入函数,以前scanf是从键盘输入到程序,现在是从文件输入到程序。

  • 参数:

    • 格式 %d %c %s这些
    • 指针 存放读取到的字符。
  • 返回值:如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回 EOF。

	hello world ABCD
	char str1[10],str2[10],*c1,*c2,*c3,*c4;
	fscanf(fp,"%s %s %c %c %c %c",str1,str2,&c1,&c2,&c3,&c4);
	printf("%s %s %c %c %c %c",str1,str2,c1,c2,c3,c4);
	已经打开了文件
	hello world A B C D
	--------------------------------
	Process exited after 0.03082 seconds with return value 0
	请按任意键继续. . .

函数9 size_t fread(void *ptr, size_t size, size_t count, FILE *stream)

  • 说明:从文件里,以二进制形式,读取文件。读取count个项,每个项的大小是size。

  • 参数:

    • ptr 读取到的数据,存放的地址。
    • size 一次读取的数据大小
    • count 这是读取的个数,每个元素的大小为 size 字节。
    • stream 文件流
  • 返回值:成功读取返回是一个整型数据类型。

函数10 size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream)

  • 说明:向文件里,以二进制形式,输出数据。读取count个项,每个项的大小是size。

  • 参数:

    • ptr 输出的数据指针。
    • size 一次输出的数据大小
    • count 输出的个数,每个元素的大小为 size 字节。
    • stream 文件流
  • 返回值:成功返回是一个整型数据类型。

	//这样就是输出成功了,写入到了文件
	char str[] = "ABCD";
	fwrite(str,sizeof(char),3,fp);

下面是关于结构体的

	typedef struct Stu{
    
    
		char *name;
		int age;
	};

1.一个结构体,写入到文件里,然后格式化输出

	Stu s;  
	s.name = "tom";	
	s.age = 21;
	//这样写的话,文件里显示是乱码
	fwrite(&s,sizeof(Stu),1,fp);
	//因为是格式化输出,不是乱码
	fprintf(fp,"%s %d",s.name,s.age);

2.一个结构体写入到文件里,查看文件,是乱码。 因为是二进制模式打开的,所以是乱码,所以使用格式化的打印,不会出现乱码的情况。

	//写入成功,但是,此时文件里是乱码。
	Stu *s1 = (Stu*)malloc(sizeof(Stu*));  
	s1->name = "tom";	
	s1->age = 21;
	fwrite(s1,sizeof(Stu),1,fp);

3.一个结构体,写入到文件里,再读取出来。注意要光标重定位,否则会出现错误。

	//写+读
	Stu *s1 = (Stu*)malloc(sizeof(Stu*));
	Stu *s2 = (Stu*)malloc(sizeof(Stu*));  
	s1->name = "tom";	
	s1->age = 21;
	//往文件里写
	fwrite(s1,sizeof(Stu),1,fp);
	//重定位一下光标 很重要
	rewind(fp);
	//从文件中读取
	fread(s2,sizeof(Stu),1,fp);
	printf("%s %d\n",s1->name,s1->age);
	printf("%s %d",s2->name,s2->age);
	
	tom 21
	tom 21
	--------------------------------
	Process exited after 0.03888 seconds with return value 0
	请按任意键继续. . .

其他函数

  • int feof(FILE *stream)
    • 当到了文件结尾的时候,该函数返回一个非零值,否则返回零,判断的时候 !feof(FILE)就是没到结尾
  • int ferror(FILE *stream)
    • 当前的流出错,函数返回一个非零值,否则返回一个零值。if( ferror ){出错}
  • void rewind(FILE *stream)
    • 定位光标到开头
  • int fseek(FILE *stream, long int offset, int whence)
    • 改变当前光标的位置
    • stream 文件流
      offset 这是相对 whence 的偏移量,以字节为单位。
      whence 这是表示开始添加偏移 offset 的位置。它一般指定为下列常量之一:
      SEEK_SET 文件的开头
      SEEK_CUR 文件指针的当前位置
      SEEK_END 文件的末尾
  • long int ftell(FILE *stream)
    • 返回光标当前位置。
  • 这里面光标的意思就是文件指针。

猜你喜欢

转载自blog.csdn.net/weixin_42585456/article/details/105982277