目录
一,文件
1.文本模式,二进制模式
2.标准文件
二,文件的打开和关闭
1.文件指针
1.1文件的打开
1.2文件的关闭
三,文件的顺序读写
1.fgetc
2.fputc
3.fgets
4.fputs
5.fprintf
6.fscanf
7.fwrite
8.fread
9.表格
四,文件的随机读写
1,fseek
2,ftell
3,rewind
判断文件结束
1,feof
2,判断结束
文件使用模式(表格)
文本文件的部分代码示例
二进制文件的部分代码
C把文件看作是一系列的连续的字节,每个字节都能被单独读取。
C提供两种文件模式:文本模式和二进制模式
首先要区分文本内容和二进制内容,文本文件格式和二进制文件格式,及文件的文本模式和二进制模式。
c程序自动打开的三个文件
每个被使用的文件都在内存中开辟了一个相对应的文件信息区,用来存放文件的相关信息。这些信息是保存在一个结构体变量中的,这个结构体类型是由系统声明的取名FILE(文件)。
定义一个文件指针变量:
FILE * pf ;//文件指针变量,指向被操作的文件
打开文件我们用到一个打开文件的函数 fopen()查找库函数得知 :
所以我们用文件指针接受打开的文件可操作流:
FILE * pf = fopen("文件名.后缀","打开方式");
//打开文件之后要判断有没有打开成功
if(pf==NULL) //打开失败返回NULL
perror("fopen");
//perror报错函数,会打印括号里面的错误信息
流是一个高度抽象的概念:
程序直接传输到外部设备比较繁琐,所以写入流,让流操作
下述所有的流 同时包括 FILE文件指针pf。
关闭与流关联的文件并取消关联,使用fcloae():
fclose(pf);//关闭文件
pf=NULL; //置空指针
注意:
先简单介绍所有的读写函数,然后再附上表格。
所有用到的pf都表示文件指针。
从流中获取字符
参数是标准输入流
读一次向后移动 1 ,类似于指针的 ++ ,当读取超出文件长度 出EOF(-1) ;
int ret = fgetc(pf);
将字符写入流
两个参数一个是 字符,一个是 标准输出流(stdout,stderr)
fputc('字符',输出流);
从流中获取字符串写入目标数组
第一个参数是 目标数组的指针;
第二个复制到数组的最大个数(n-1个,最后一个放'\0');
第三个参数是标准输入流。
fgets(arr,4,pf);
将字符串写入流
第一个参数是要写入流的地址指针;
第二个参数是标准输出流。
fputs("abcdef\n",pf);
将格式化数据写入流
第一个参数是标准输出流
第二个参数是格式化字符串等一系列的东西
Typedef struct S{
char arr[10];
int num;
float sc;
}s;
fprintf(pf,"%s %d %d ",s.arr,s.num,s.sc) ;
从流中读取格式化数据
第一个参数是标准输入流
第二个参数是格式化字符串等一系列的东西
fscanf(pf,"%s %d %f",&(s.arr),&(s,num),&(s.sc));
以二进制的方式写文件
第一个参数是写入元素数组的指针
第二个参数是要写入的每个元素的大小(单位字节)
第三个参数是要写入的元素个数
第四个参数是要被写入的地址
fwrite(&s,sizeof(struct S) , 1 ,pf) ;
//从s中找到1个元素,元素大小是sizeof(struct S)的数据,写到pf中
以二进制的方式读文件
第一个参数是接收读取文件内容的地址
第二个参数是要读取文件的大小
第三个参数是要读取文件的个数
第四个参数是被读取文件的地址
fread(&s,sizeof(struct S),1,pf);
//从pf里读取1个大小为sizeof(struct S)的文件到s中去
函数 | 功能 | 适用于 |
fgetc | 字符输入函数(读文件) | 所有输入流 |
fputc | 字符输出函数(写文件) | 所有输出流 |
fgets | 文本行输入函数(读一行) | 所有输入流 |
fputs | 文本行输出函数(写一行) | 所有输出流 |
fscanf | 格式化输入函数 (读) | 所有输入流 |
fprintf | 格式化输出函数(写) | 所有输出流 |
fread | 二进制输入 (读) | 文件 |
fwrite | 二进制输出 (写) | 文件 |
这里会有些迷惑,为什么输出函数后面会标注 写,输入函数后面 标注 读 。
这里的读写 是面向内存的,也就是说对于用户来说的输入,对于内存来说是读,就是读取用户的输入信息,或者是别的位置的数据;对用户来说的输出,对于内存来说是写,就是写出信息让用户可以看到。
根据文件指针的位置和偏移量来定位文件指针
第一个参数 流
第二个参数 偏移量
第三个参数 起始位置
起始位置选项: SEEK_CUR :文件当前位置开始
SEEK_END : 文件末尾位置开始
SEEK_SET : 文件起始位置开始
返回文件指针的当前位置
参数是 流
让文件指针回到起始位置
参数是 流
当文件读取结束时,判断文件是读取失败结束,还是遇到文件尾(读取完成)结束。
判断结束不可以用feof的返回值直接判断文件是否结束,但可以通过以下几种方式:
文件使用方式 | 含义 | 如果指定文件不存在 |
" r " (只读) | 为了输入数据,打开一个已经存在的文本文件 | 出错 |
" w " (只写) | 为了输出数据,打开一个文本文件 | 建立一个新的文件 |
" a " (追加) | 向文本文件尾部添加数据 | 建立一个新的文件 |
" rb " (只读) | 为了输入数据,打开一个二进制文件 | 出错 |
" wb " (只写) | 为了输出数据,打开一个二进制文件 | 建立一个新的文件 |
" ab " (追加) | 向一个二进制文件尾部添加数据 | 出错 |
" r+ " (读写) | 为了读写,打开一个文本文件 | 出错 |
" w+ " (读写) | 为了读写,建立一个新的文本文件 | 建立一个新的文件 |
" a+ " (读写) | 打开一个文件,在文件尾部进行读写 | 建立一个新的文件 |
"rb+ " (读写) | 打开一个二进制文件(读写) | 出错 |
" wb+ " (读写) | 建立一个新的二进制文件(读写) | 建立一个新的文件 |
" ab+ " (读写) | 打开一个二进制文件,在文件尾部进行读和写 | 建立一个新的文件 |
" wx " ," wbx " , " w+x " , " wb+x " 或 " w+bx "
类似于不含有x的模式,如果文件已经存在或以独占模式被打开,则打开文件失败
int c; //处理EOF,EOF的值是-1,不可以用 char类型
FILE *pf = fopen("test.c","r") ;//这里的文件名知识一个例子
if(!pf)//判断打开文件是否成功
{
perror("FILE error");
return EXIT_FAILURE;//值为1, 运行程序失败
}
//fgetc读取失败时或者遇到文件结尾时返回EOF
while((c = fgetc(pf) ) != EOF)
{
putchar(c);
}
//判断结束原因
if(ferror(pf))
{
printf("I/O error");
}
else if(feof(pf) ) //前一个没有出现错误说明是正常结束
{
printf("END of FILE ……");
}
//ferroe 初始化为0 ,返回非0 的时表面出错
//关闭文件
fclose(pf);
enum {
size = 5
};
//枚举 ,后面的size大小是5
double a[size] = { 1,2,3,4,5 };
FILE * pf = fopen("test.c", "wb"); //打开文件
fwrite(a, sizeof(a), size, pf); //fwirte的返回值是一个size_t类型
fclose(pf);//关闭文件
double b[size];
FILE * pf = fopen("test.c", "rb");
size_t ret = fread(b, sizeof(b), size, pf);//读取
if(ret == 1) //当ret == 1 时,读取成功
{
puts("successfully :");
for (int n = 0; n < size; n++)//打印内容
{
printf("%f ",b[n]);
}
putchar('\n');
}
else //失败时判断失败的原因
{
if (feof(pf))
{
printf("end of file:");
}
else if (ferror(pf))
{
perror("Error:");
}
}
fclose(pf);//关闭文件
上述两个代码段,需要放到具体内容里,用合适的变量接受具体的返回值,返回值类型上文都有介绍。