9 文件
主要是涉及一些函数的操作。
只有带有写操作,才会建立,否则都是报错!
区分好读写数据到磁盘文件的函数
9.1 fopen打开数据文件
FILE *fopen(char *pname, char *mode) { FILE *fp; fp = fopen("c:\\temp\\test.txt", "r"); if(fp == NULL)//注意这里的NULL必须要大写 printf("fail to open the file! \n"); else { printf("The file is open! \n"); fclose(fp); } }
9.2 用fclose函数关闭数据文件
fclose(fp); //当成功执行了关闭操作,则返回值为0;否则返回EOF(-1);
9.3 读写数据
本质是控制台与文件做交互,对比显示器就是原先put到显示器的东西变为磁盘文件,即交互的对象改变而已,其余不改变!
不确定的时候可以用等价:getc-gets-fscanf-fread;putc-puts-fprintf-fwrite;
9.3.1 读入一个字符
- fgetc
从fp指向的文件读入一个字符,失败返回结束标志EOF(-1)
- fputc
从字符ch写到文件指针fp所指向的文件,失败返回EOF
判断文件是否读取完毕 ,可利用feof()进行检查。
- 未完成返回0
- 完成返回非零值
//使用feof以及fgetc的小demo while(!feof(fp)) { printf("%c",fgetc(fp)); }
{ char ch;//输入要先定义存放 ch=getchar(); fputc(ch,fp); //不同的打开方式决定了,输入的方式,比如w+,从开头写,如果文件内有内容,则覆盖;a+采用在末尾追加 }
9.3.2 读入一个字符串
- fgets:读入一个**长度(n-1)**的字符串,存放到字符数组str中;
读成功,返回str地址
失败,返回NULL
{ char *str;//这是一个经典错误,定义指针不开拓空间,是没法直接用的。改为下方: char str[10]; fgets(str,4,fp); puts(str); }
- fputs:把str指向的字符串写到fp所指向的文件中
成功,返回0
失败,返回非0值
{ str="new world!"; fputs(str,fp); }
评注:
- 从文件读入到数据区,需要制定size;而从数据区到文件不要指定size。
- 共性:都需要通过字符串数组或指针做中介。
9.3.3 用格式化的方式读写文件
这四种读写方式中,只有格式化在括号内先出现文件指针
{ //fprint(文件指针,格式化字符,输出列表) int i=3; fprint(fp,"%d",i); //实现的功能就是将i的值写到磁盘文件中 //fscanf(文件指针,格式化字符,输入列表) fscanf(fp,"%d",&i); //从文件中取一个数字存储到变量i中 }
9.3.4 用二进制方式向文件读写一组数据
{ fread(buffer,size,count,fp); fwrite(buffer,size,count,fp); /* 1. buffer:一个目标地址。fread时,把文件读入的数据存储到这个地址,fwrite,把这个区域的数据向文件输出 2. size:读写的字节数 3. count:读写多少个数据项(每个数据项长度为size) 4. fp:FILE类型指针 */ }
记忆方式:
read读文件,既然是读文件,肯定是将文件中的数据读出来存到别处;
//文件复制 { #include<stdio.h> int main() { FILE *src = fopen("c:\\test\\test.pdf", "rb"); // 源文件 if (src == NULL) { printf("Error opening file"); return -1; } FILE *dst = fopen("c:\\test\\in.pdf", "wb"); // 需要拷贝的目标文件 char buf[64] = { 0 }; // 一次读取 64B的大小 while (!feof(src)) { int len = fread(buf, sizeof(char), sizeof(buf), src); // 注意这里写入的大小一定要使用读取返回的大小 len, // 否则很可能出现文件末尾多写入了很多个 0 的情况 fwrite(buf, sizeof(char), len, dst); } fclose(src); fclose(dst); printf("copy end\n"); return 0; } }
上方是一个文件拷贝的例子,里面最重要的是buffer缓冲区通过构建一个字符数组生成,保证缓冲区的大小,一个字节一个字节存储拷贝,生成的len的论坛和就是一次拷贝的大小,read,write的size保持一致。这里的文件拷贝也可以通过其他读写形式实现
9.4 (*)随机读写数据文件
9.4.1 文件位置标记及其定位
1 rewind函数
使文件位置标记重新返回文件的开头,此函数没有返回值。
rewind(fp);
2 fseek 函数
描述:
#define SEEK_CUR 1 // 当前位置 #define SEEK_END 2 // 末尾 #define SEEK_SET 0 // 开头 fseek(文件类型指针,位移量,起始点); //位移量:应是long型数据,在数字末尾添加一个L,就表示long型,使用负号在前时,表示后退
举例:
{ fseek(fp,100L,0); //将文件位置移动到距文件开头100个字节处 fseek(fp,50L,1); fseek(fp,-10L,2); //将文件位置从文件末尾向后退10个字节 }
3 ftell
获取当前位置的偏移量
long int ftell ( FILE * stream );//成功返回指针相对于开头的偏移量,失败返回 -1
//使用以上fseek,ftell函数,可以轻松获取到文件的大小: #include <stdio.h> int main () { FILE * pFile; long size = 0; // 文件大小 pFile = fopen ("D:\\myfile.txt","rb"); if (pFile==NULL) ("Error opening file"); else { fseek (pFile, 0, SEEK_END); // 直接定位到文件末尾 size = ftell (pFile); // 获取到当前指针的偏移量,即文件大小 fclose (pFile); printf ("Size of myfile.txt: %ld bytes.\n", size); } return 0; }
4 将缓冲区内容写入文件
实际上,当我们在执行文件写入操作时,写入的内容只是保留在了一个缓冲区内,并没有实时写入到文件中去,而是等到 fclose 或者程序终止时才写入。
使用下面这个函数则可以将缓冲区的内容即时写入到文件中去:
int fflush ( FILE * stream );
- 成功返回 0,失败返回 EOF。
- 优点:
防止由于断电或者死机造成重要数据没有写入到文件中而导致数据丢失。
- 缺点:
磁盘读写次数增加,影响程序执行效率,降低磁盘使用寿命。
9.5 检测文件状态函数
9.5.1 ferror函数
int ferror(FILE *fp); //测试文件是否出现错误
- 未出错:返回0
- 出错:返回1
说明:
- 每次调用文件输入输出函数,均产生一个新的ferror函数值,所以应及时测试
- fopen打开文件时,ferror函数初值自动置为0
9.5.2 clearerr函数(清除错误)
作用:将文件错误标志和文件结束标志置为0。
说明:出现错误标志,他就一直保留,直到对同一文件调用clearerr函数或rewind函数,或其他任何一个输入输出函数。
#include<stdio.h> int main() { FILE *stream; stream=fopen("test","w"); gets(stream); if(ferror(stream)) { printf("Error reading"); clearerr(stream); } if(!ferror(stream)) printf("Error indicator cleared"); fclose(stream); return 0; }