我们用下面两个函数实现文件的打开和关闭
对于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);