文件的打开和关闭
我们用下面两个函数实现文件的打开和关闭
对于fopen来说,第一个参数传入一个文件的名字,第二个为打开的方式,返回值为一个文件指针,如果打开失败就返会NULL
fclose里的参数为传入一个文件指针
我们来看具体的例子
int main() { FILE* pf = fopen("text.txt", "r");//用pf来接收 if (pf == NULL) { perror("fopen"); return 1; } //关闭文件,指针置为空 fclose(pf); pf = NULL; return 0; }
上面我们是以"r"的方式打开一个文件名为"text.txt"的文本文件,那么下面我们来介绍一下打开方式
我们上面的代码中是采取了 “r” 的方式打开文件,但是在此之前项目文件夹里并没有目标文件,所以打开文件失败,运行报错
文件的读写
文件的写入
接下来我们来了解一下文件的读写函数
我们先来认识一下fgetc()函数,首先第一个参数需要传入一个字符,第二个参数为目标流
int main() { FILE* pf = fopen("text.txt", "w");//选用w的方式打开文件 if (pf == NULL) { perror("fopen"); return 1; } fputc('a', pf); fputc('\n', pf); for (char c = 'a'; c <= 'z'; c++) { fputc(c, pf); } //关闭文件,指针置为空 fclose(pf); pf = NULL; return 0; }
当采用w的方式打开文件后,自动创建了一个"text.txt"文件,之后调用了fputc函数向文件中写入字符
这样一个字符一个字符的写入有点麻烦,还可以通过fputs()函数实现写入一个字符串
fputs("hello word",pf);
也就是把写入文件的代码换成上面的
格式化写入
如果需要指定写入的格式的话就用到了 fprintf()函数
下面是具体使用方法
struct person { char name[20]; int age; }; int main() { struct person p = { "zhangsan",20 }; FILE* pf = fopen("text.txt", "w"); if (pf == NULL) { perror("fopen"); return 1; } //格式化写入 fprintf(pf, "%s %d", p.name, p.age); fclose(pf); pf = NULL; return 0; }
可以看出,fprintf的参数类型只比printf多了一个流
文件的读取
接下来介绍一下fgetc()函数,如果读取成功,返回的是字符的ASCII码值,如果读取到文件末尾或者读取失败,返回EOF(-1)
int main() { //FILE* pf = fopen("text.txt", "w"); FILE* pf = fopen("text.txt", "r"); if (pf == NULL) { perror("fopen"); return 1; } /*for (char c = 'a'; c <= 'z'; c++) { fputc(c, pf); }*/ char a1 = fgetc(pf); printf("%c\n", a1); char a2= fgetc(pf); printf("%c\n", a2); //关闭文件,指针置为空 fclose(pf); pf = NULL; return 0; }
在以w的方式打开之后写入字符,再以r的方式打开读取字符,讲函数返回值接受并以字符形式打印,读取是按照顺序依次往下读取,根据读取到文件末尾返回值为EOF,可以用一个循环来实现对文件中所有字符进行遍历。
同理,也可以一次读取一个字符串,使用的函数就是与之对应的fgets()
** fgets()的使用 **
fgets需要传入三个参数,第一个是接受字符串的指针,第二个是读取的字节数,第三个是读取的流,读取成功的话返回字符串的指针,读取失败或者读取到文件末尾,返回NULL
char arr[10] = {0}; fgets(arr,10,pf); printf("%s",arr);
有一点需要注意的是,虽然是读取10个字节,但是第10个位置要预留给’\n’
格式化读取
与fprintf对应的就是fscanf,使用方法也与scanf类似
struct person { char name[20]; int age; }; int main() { struct person p = { "zhangsan",20 }; FILE* pf = fopen("text.txt", "r"); if (pf == NULL) { perror("fopen"); return 1; } //格式化写入 //fprintf(pf, "%s %d", p.name, p.age); //格式化读取 fscanf(pf, "%s %d", p.name, &(p.age)); printf("%s %d\n", p.name, p.age); fclose(pf); pf = NULL; return 0; }
二进制文件的写入和读取
int main() { int arr[] = { 1,2,3,4,5 }; FILE* pf = fopen("text.txt", "wb");//二进制形式打开 if (pf == NULL) { perror("fopen"); return 1; } int sz = sizeof(arr) / sizeof(arr[0]); //以二进制形式写入 fwrite(arr, sizeof(arr[0]), sz, pf); // 参数依次为写入的目标指针,每个元素大小(字节),写入元素个数,写入流的形式 fclose(pf); pf = NULL; return 0; }
由于是以二进制形式写入,所以文本形式下看不出来写入的内容,需要以二进制形式读取
int main() { int arr[] = { 1,2,3,4,5 }; FILE* pf = fopen("text.txt", "rb");//二进制形式打开 if (pf == NULL) { perror("fopen"); return 1; } int sz = sizeof(arr) / sizeof(arr[0]); //读取二进制文本 fread(arr, sizeof(arr[0]), 1, pf); // 参数依次为写入的目标指针,每个元素大小(字节),一次读取个数,写入流的形式 printf("%d", arr[0]); fclose(pf); pf = NULL; return 0; }
文件的随机读取
上面的文件操作函数都是按照顺序进行读取,接下来介绍一下随机读取的函数
int main() { FILE* pf = fopen("text.txt", "r"); if (pf == NULL) { perror("fopen"); return 1; } char c = fgetc(pf); printf("%c\n", c); fseek(pf, 3, SEEK_CUR);//光标从当前位置偏移量为3 c = fgetc(pf); printf("%c\n", c); fclose(pf); pf = NULL; return 0; }
当text.txt文件中为abcdefg时运行结果
结合这些操作就可以实现访问任意元素
ftell()
ftell函数返回的是文件指针相对于起始位置的偏移量
printf("%d",ftell(pf));
函数只有一个参数,返回值为偏移量
rewind()
rewind函数的作用就是返回到文件的起始位置
rewind(pf);