文件操作
文件
在电脑的D盘,C盘等等中的所有东西都叫文件,在程序设计中,一般有两种文件,一个是程序文件(与程序有关的或者程序产生的),另一个是数据文件(程序运行时读写数据的)。
一个文件要有一个唯一的文件名,以便识别。文件名一般包含三个部分:文件路径+文件名主干+文件后缀,例如D:\C语言\文件操作.txt,用来存放相关信息
文件的打开和关闭
对文件进行操作的时候,需要先打开文件,再读/写文件,最后再关闭文件。文件打开时,在内存中创建文件信息区。
文件信息区的类型是一个FILE类型的,FILE是一个结构体,定义为typedef struct _iobuf FILE,不同的编译器FILE包含的类型不同。通过定义一个FILE*类型的指针变量(例如pf),可以访问文件中的信息。
C语言中打开文件函数为fopen,MSDN上解释为 FILE *fopen( const char *filename, const char *mode );,第一个变量filename是文件名,第二个变量mode是打开文件的方式。
打开文件的方式也有很多种,例如‘r’是读,打开一个已经存在了着的文件以输入数据,‘w’是写,打开一个文件输出数据,‘a’是追加,在文本文件末尾追加数据。打开文件成功,返回一个FILE类型的指针,打开文件失败,则返回空指针。
关闭文件函数为fclose,MSDN上解释为int fclose( FILE *stream );
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE* pf = fopen("text.c","r");//相对路径
//FILE* pf = fopen("D:\\c语言\\Contact\\text.c","r");
//绝对路径
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return -1;
}
else
{
printf("打开成功\n");
}
fclose(pf);
return 0;
}
'r’只能用于读一个已经创建了的文件,如果文件没有创立,可以选择用’w‘的方式创建一个新文件。(z注意’w’只能打开一个空文件,如果文件中已经有类型了,那么就会对内容进行销毁)
FILE* pf = fopen("D:\\c语言\\Contact\\text.c","w");
文件的读写方式
文件的读写方式有两种,一种是顺序读写,一种是随机读写。
![](https://img-blog.csdnimg.cn/af3f904e73214cbcbd1d1c71b3aa419b.png)
顺序读写函数
fgetc和fputc
函数 | 作用 | 解释 | 适用 |
---|---|---|---|
fgetc | 字符输入函数 | int fgetc( FILE *stream ); | 所有输入流 |
fputc | 字符输出函数 | int fputc( int c, FILE *stream ); | 所有输出流 |
流是磁盘或其它外围设备中存储的数据的源点或终点,也就是说通过流,可以将数据操作在文件,屏幕,网站,软件等等上,C语言程序一但运行,就默认打开了三个流,标准输出流(stdout),标准输入流(stdin),标准错误流(stderr),(三者的类型都是FILE*)。
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE* pf = fopen("D:\\c语言\\Contact\\text.txt","w");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return -1;
}
else
{
printf("打开成功\n");
}
fputc('a', pf);//每次写入一个之后指针向后偏移
fputc('b', pf);
fputc('c', pf);
fclose(pf);
return 0;
}
int main()
{
FILE* pf = fopen("D:\\c语言\\Contact\\text.txt","r");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return -1;
}
else
{
printf("打开成功\n");
}
int ch = fgetc(pf);//每次读出后向后偏移
printf("%d ", ch);
ch = fgetc(pf);
printf("%d ", ch);
ch = fgetc(pf);
printf("%d ", ch);
//输出为97 98 99,即a,b,c的ASCII码值
fclose(pf);
return 0;
}
fputs和fgets
函数 | 作用 | 解释 | 适用 |
---|---|---|---|
fgets | 文本行输入函数 | char *fgets( char *string, int n, FILE *stream ); | 所有输入流 |
fputs | 文本行输出函数 | int fputs( const char *string, FILE *stream ); | 所有输出流 |
int main()
{
FILE* pf = fopen("D:\\c语言\\Contact\\text.txt","w");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return -1;
}
else
{
printf("打开成功\n");
}
fputs("hello\n", pf);
fputs("world!\n", pf);
fclose(pf);
return 0;
}
写入操作后在文本文件中显示hello world。
char *fgets( char *string, int n, FILE *stream );函数中第一个参数是字符串,读取文件中的字符串放在该字符串中。n是读取的个数,stream是文件指针。
int main()
{
FILE* pf = fopen("D:\\c语言\\Contact\\text.txt","r");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return -1;
}
else
{
printf("打开成功\n");
}
char arr[20] = { 0 };
fgets(arr,5, pf);
printf("%s\n", arr);
fgets(arr,5, pf);//再次读取时,覆盖arr
printf("%s\n", arr);
fclose(pf);
return 0;
}
文件中的数据为hello world,读取后这里显示为
![](https://img-blog.csdnimg.cn/afadf6961aa1415f93be2f09301d0d63.png)
函数读取5个元素,但是实际上读取的只有4个,最后一位自动置为\0,所以显示如上。
fscanf和fprintf
函数 | 作用 | 解释 | 适用 |
---|---|---|---|
fscanf | 格式化输入函数 | int fscanf( FILE *stream, const char *format [, argument ]… ); | 所有输入流 |
fprintf | 格式化输出函数 | int fprintf( FILE *stream, const char *format [, argument ]…); | 所有输出流 |
对比printf和fprintf,scanf在MSDN上解释为 int printf( const char *format [,argument]… );,fprintf相对于printf来说多了一个参数FILE *stream。
struct Data
{
int x;
float y;
};
int main()
{
struct Data data = { 5,2.4 };
FILE* pf = fopen("D:\\c语言\\Contact\\text.txt","w");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return -1;
}
else
{
printf("打开成功\n");
}
//写文件
fprintf(pf, "%d %f", data.x, data.y);
fclose(pf);
return 0;
}
对比scanf和fscanf,scanf在MSDN上解释为 int scanf( const char *format [,argument]… );,fscanf相对于scanf来说多了一个参数FILE *stream。
struct Data
{
int x;
float y;
};
int main()
{
struct Data data = { 0 };
FILE* pf = fopen("D:\\c语言\\Contact\\text.txt","r");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return -1;
}
else
{
printf("打开成功\n");
}
//读取数据
fscanf(pf, "%d %f", &(data.x), &(data.y));
printf("%d %f", data.x, data.y);
fclose(pf);
return 0;
}
fread和 fwrite
函数 | 作用 | 解释 | 适用 |
---|---|---|---|
fread | 二进制输入函数 | size_t fread( void *buffer, size_t size, size_t count, FILE *stream ); | 文件 |
fwrite | 二进制输出函数 | size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream ); | 文件 |
fwrite函数中,buffer指向被写的数据,size是要写的元素的大小,单位是字节,count是要写的个数,stream是文件指针。
struct Data
{
int x;
float y;
char z;
};
int main()
{
struct Data data = {1,2.4,'a'};
FILE* pf = fopen("D:\\c语言\\Contact\\text.txt","wb");
//wb是以二进制的方式进行只写操作
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return -1;
}
else
{
printf("打开成功\n");
}
fwrite(&data, sizeof(struct Data), 1, pf);
fclose(pf);
return 0;
}
这个时候在文本文件中的显示如下,因为fwrite是以二进制的形式进行存储的,所以在文件中的显示方式也是二进制的形式,
![](https://img-blog.csdnimg.cn/74eee6bf6671476699ed53f2c17c2197.png)
fread函数和fwrite类似,buffer指向被存入数据的地址,size是要读的元素的大小,count是要读的个数,stream是文件指针。
struct Data
{
int x;
float y;
char z;
};
int main()
{
struct Data data = {0};
FILE* pf = fopen("D:\\c语言\\Contact\\text.txt","rb");
//rb是以二进制的形式读
if (pf == NULL)
{
printf("%s\n", strerror(errno));
return -1;
}
else
{
printf("打开成功\n");
}
fread(&data, sizeof(struct Data), 1, pf);
printf("%d %f %c", data.x, data.y, data.z);
fclose(pf);
return 0;
}
此时的显示为,
![](https://img-blog.csdnimg.cn/1f5698737a594674b24e3c8abc821524.png)
sscanf和sprintf
函数 | 作用 | 解释 |
---|---|---|
sscanf | 读一个格式化的数据到字符串 | int sscanf( const char *buffer, const char *format [, argument ] … ); |
sprintf | 写一个格式化的数据到字符串 | int sprintf( char *buffer, const char *format [, argument] … ); |
struct Data
{
int x;
float y;
char z;
};
int main()
{
struct Data data = { 1, 2.4, 'a' };
char arr[100] = { 0 };
sprintf(arr,"%d %f %c",data.x, data.y, data.z );
printf("%s", arr);
return 0;
}
sprintf即把一个格式化的数据(data.x, data.y, data.z)转换到了arr字符串里面。
#include <stdio.h>
#include <stdlib.h>
struct Data
{
int x;
float y;
char z;
};
int main()
{
struct Data data1 = { 1, 2.4, 'a' };
struct Data data2 = { 0 };
char arr[100] = { 0 };
sprintf(arr,"%d %f %c",data1.x, data1.y, data1.z );
sscanf(arr, "%d %f %c", &(data2.x), &(data2.y), &(data2.z));
//从arr1字符串中提取一个格式化的数据
printf("%d %f %c", data2.x, data2.y, data2.z);
return 0;
随机读写函数
fseek
feek为随机读取函数,可以将文件指针移动到指定的位置。在MSDN上解释为int fseek( FILE *stream, long offset, int origin );,origin为文件的位置,MSDN上定义了文件指针的相关位置,SEEK_CUR为文件的当前位置,SEEK_END为文件的末尾位置,SEEK_SET为文件的起始位置。
int main()
{
FILE* pf = fopen("D:\\c语言\\Contact\\text.txt", "r");
if (pf == NULL)
{
perror("失败");
return -1;
}
fseek(pf, 2, SEEK_SET);
int ch = fgetc(pf);
printf("%c", ch);
//c读取完成之后向后偏移了一位
fseek(pf, -2, SEEK_CUR);
ch = fgetc(pf);
printf("%c", ch);
return 0;
}
设原始数据为abcd,输出为cd。
ftell
ftell函数可以用来计算文件指针相对于起始位置的偏移量。MSDN上解释为long ftell( FILE *stream );
int main()
{
FILE* pf = fopen("D:\\c语言\\Contact\\text.txt", "r");
if (pf == NULL)
{
perror("失败");
return -1;
}
fseek(pf, 2, SEEK_SET);
int ch = fgetc(pf);
printf("%c", ch);
int x = ftell(pf);
printf("%d", x);
//输出为3
return 0;
}
rewind
rewind函数是让文件指针回到文件的起始位置。在MSDN上解释为void rewind( FILE *stream );
int main()
{
FILE* pf = fopen("D:\\c语言\\Contact\\text.txt", "r");
if (pf == NULL)
{
perror("失败");
return -1;
}
fseek(pf, 2, SEEK_SET);
int ch = fgetc(pf);
printf("%c", ch);
rewind(pf);
//回到起始位置
ch = fgetc(pf);
printf("%c", ch);
//设文件中为abcd,打印为a
return 0;
}