文件写入
基础示例
核心代码:
fprintf(fp, "hello c file!\n");
完整代码:
#include <stdio.h>int main() {// 文件类型的指针FILE *fp = NULL;// 以只写方式打开文件fp = fopen("test.txt", "w"); // r w a r+ w+ a+// 判断是否打开成功if (fp == NULL) {printf("open failed!\n");return -1;}printf("open success!\n");// 写入文件fprintf(fp, "hello c file!\n");// 关闭文件fclose(fp);// 置空,释放内存fp = NULL;return 0;
}
fprintf按照指定格式写入文件
核心代码:
int i = 33;
char c[] = "zhangdapeng";
double d = 33.33;
fprintf(fp, "%d %s %lg\n", i, c, d);
完整代码:
#include <stdio.h>int main() {// 文件类型的指针FILE *fp = NULL;// 以只写方式打开文件fp = fopen("test.txt", "w"); // r w a r+ w+ a+// 判断是否打开成功if (fp == NULL) {printf("open failed!\n");return -1;}printf("open success!\n");// 写入文件int i = 33;char c[] = "zhangdapeng";double d = 33.33;fprintf(fp, "%d %s %lg\n", i, c, d);// 关闭文件fclose(fp);// 置空,释放内存fp = NULL;return 0;
}
练习:读写格式字符
需求:
- 将int类型,字符串类型,double类型的三个变量的值按照空格分割写入到test.txt文件中
- 读取test.txt中的一行文本,然后转换为int类型,字符串类型和double类型的变量并输出
编写write.c,实现格式化写入的功能代码:
#include <stdio.h>int main(){FILE *fp = NULL;fp = fopen("test.txt", "w");if (fp == NULL){printf("open failed!\n");return -1;}printf("open success!\n");int age = 33;char name[] = "zhangdapeng";double weight = 83.7;fprintf(fp, "%d %s %lg\n", age, name, weight);fclose(fp);fp = NULL;return 0;
}
使用gcc编译:
gcc write.c -o write
执行:
./write
查看当前目录:
ls
查看文件内容:
cat test.txt
输出:
33 zhangdapeng 83.7
编写read.c,实现读取格式化字符的功能。
#include <stdio.h>int main(){FILE *fp = NULL;fp = fopen("test.txt", "r");if (fp == NULL){printf("open failed!\n");return -1;}printf("read the test.txt success!\n");int newAge;char newName[128];double newWeight;fscanf(fp, "%d %s %lg\n", &newAge, newName, &newWeight);printf("newAge = %d, newName = %s, newWeight = %f\n", newAge, newName, newWeight);fclose(fp);fp = NULL;printf("read the format string success!\n");return 0;
}
编译代码:
gcc read.c -o read
执行代码:
./read
输出:
read the test.txt success!
newAge = 33, newName = zhangdapeng, newWeight = 83.700000
read the format string success!
标准输出
stdin标准输入,stdout标准输出,stderr标准错误输出。
核心代码:
fprintf(stdout, "%d %s %lg\n", i, c, d);
示例代码:
#include <stdio.h>int main() {// 文件类型的指针FILE *fp = NULL;// 打开文件fp = fopen("test.txt", "r"); // r w a r+ w+ a+// 判断是否打开成功if (fp == NULL) {printf("open test.txt failed!\n");return -1;}// 读取文件int i;char c[128];double d;fscanf(fp, "%d %s %lg\n", &i, c, &d);// 输出fprintf(stdout, "%d %s %lg\n", i, c, d);// 关闭文件fclose(fp);// 置空,释放内存fp = NULL;return 0;
}
输出:
33 zhangdapeng 33.33
fputc每次写一个字符
示例代码:
#include <stdio.h>int main() {// 文件类型的指针FILE *fp = NULL;// 打开文件fp = fopen("test.txt", "a");// 判断是否打开成功if (fp == NULL) {printf("open test.txt failed!\n");return -1;}// 每次写一个字符fputc('a', fp);fputc('b', fp);fputc('c', fp);// 关闭文件fclose(fp);// 置空,释放内存fp = NULL;return 0;
}
fputs写入字符串到文件
#include <stdio.h>int main() {// 文件类型的指针FILE *fp = NULL;// 打开文件fp = fopen("test.txt", "w");// 判断是否打开成功if (fp == NULL) {printf("open failed!\n");return -1;}// 写入字符串fputs("abc1\n", fp);fputs("abc2\n", fp);fputs("abc3\n", fp);// 关闭文件fclose(fp);// 置空,释放内存fp = NULL;return 0;
}
fwrite按块写入文件
这个方法非常适合处理大文件。如果要写入大型文件,优先考虑使用此方法。
#include <stdio.h>int main() {// 文件类型的指针FILE *fp = NULL;// 打开文件fp = fopen("test.txt", "w");// 判断是否打开成功if (fp == NULL) {printf("open failed!\n");return -1;}// 写入文件char buf[] = "abc";int count = fwrite(buf, 1, sizeof(buf), fp);printf("写入了%d个字节的数据\n", count);// 关闭文件fclose(fp);// 置空,释放内存fp = NULL;return 0;
}
fwrite写入结构体数组
#include <stdio.h>typedef struct person {int id;char name[32];
} Person;int main() {// 文件类型的指针FILE *fp = NULL;// 打开文件fp = fopen("test.txt", "w");// 判断是否打开成功if (fp == NULL) {printf("open failed!\n");return -1;}// 结构体数组Person arr[] = {{1, "张三"},{2, "李四"},{3, "王五"},};// 写入文件int count = fwrite(arr, 1, sizeof(arr), fp);printf("写入了%d个字节的数据\n", count);// 关闭文件fclose(fp);// 置空,释放内存fp = NULL;return 0;
}
文件读取
打开模式
- r:只读
- w:只写
- a:追加
- r+:可读可写,但是不会创建文件
- w+:可读可写,不存在则创建
- a+:追加,不存在会创建文件
- rb:读二进制文件
- wb:写二进制文件
一个程序,默认最多只能打开1024个文件。
基础示例
示例代码:
#include <stdio.h>int main() {// 文件类型的指针FILE *fp = NULL;// 以只写方式打开文件fp = fopen("test.txt", "w"); // r w a r+ w+ a+// 判断是否打开成功if (fp == NULL) {printf("open failed!\n");return -1;}printf("open success!\n");// 关闭文件fclose(fp);// 置空,释放内存fp = NULL;return 0;
}
输出:
open success!
fscanf 按照指定格式读取文件
核心代码:
int i;
char c[128];
double d;
fscanf(fp, "%d %s %lg\n", &i, c, &d);
完整代码:
#include <stdio.h>int main() {// 文件类型的指针FILE *fp = NULL;// 打开文件fp = fopen("test.txt", "r"); // r w a r+ w+ a+// 判断是否打开成功if (fp == NULL) {printf("open failed!\n");return -1;}printf("open success!\n");// 读取文件int i;char c[128];double d;fscanf(fp, "%d %s %lg\n", &i, c, &d);// 查看printf("读取结果:i=%d c=%s d=%lg\n", i, c, d);// 关闭文件fclose(fp);// 置空,释放内存fp = NULL;return 0;
}
输出:
open success!
读取结果:i=33 c=zhangdapeng d=33.33
fgetc每次读取一个字符
#include <stdio.h>int main() {// 文件类型的指针FILE *fp = NULL;// 打开文件fp = fopen("test.txt", "r");// 判断是否打开成功if (fp == NULL) {printf("open test.txt failed!\n");return -1;}// 每次读一个字符while (1) {char c = fgetc(fp);if (c == -1) {break;}printf("%c", c);};printf("\n");// 关闭文件fclose(fp);// 置空,释放内存fp = NULL;return 0;
}
feof判断文件末尾
#include <stdio.h>int main() {// 文件类型的指针FILE *fp = NULL;// 打开文件fp = fopen("test.txt", "r");// 判断是否打开成功if (fp == NULL) {printf("open test.txt failed!\n");return -1;}// 每次读一个字符char c;while (!feof(fp)) { // 使用feof判断文件末尾c = fgetc(fp);if (c > 0) {printf("%c", c);}};printf("\n");// 关闭文件fclose(fp);// 置空,释放内存fp = NULL;return 0;
}
fgets按行读取文件
#include <stdio.h>int main() {// 文件类型的指针FILE *fp = NULL;// 打开文件fp = fopen("test.txt", "r");// 判断是否打开成功if (fp == NULL) {printf("open failed!\n");return -1;}// 按行读取字符串char buf[1024];// 读第1行fgets(buf, 1024, fp);printf("%s", buf);// 读第2行fgets(buf, 1024, fp);printf("%s", buf);// 读第3行fgets(buf, 1024, fp);printf("%s", buf);// 关闭文件fclose(fp);// 置空,释放内存fp = NULL;return 0;
}
fgets按行循环读取文件
fgets读取到文件末尾或者读取失败的时候,返回NULL,可以以此作为循环退出的条件。
#include <stdio.h>int main() {// 文件类型的指针FILE *fp = NULL;// 打开文件fp = fopen("test.txt", "r");// 判断是否打开成功if (fp == NULL) {printf("open failed!\n");return -1;}// 按行读取字符串char *p = NULL;char buf[1024];// 循环读取while (1) {p = fgets(buf, sizeof(buf), fp);if (p == NULL) {break;}printf("%s", buf);}// 关闭文件fclose(fp);// 置空,释放内存fp = NULL;return 0;
}
fread按块读取文件
fread一般和fwrite配合使用,适合处理大型文件。
我们可以把上个案例写入的结构体数组读取出来。
#include <stdio.h>
#include <string.h>typedef struct person {int id;char name[32];
} Person;int main() {// 文件类型的指针FILE *fp = NULL;// 打开文件fp = fopen("test.txt", "r");// 判断是否打开成功if (fp == NULL) {printf("open failed!\n");return -1;}// 结构体数组Person arr[3];// 初始化内存memset(arr, 0, sizeof(arr));// 读取文件for (int i = 0; i < 3; ++i) {int count = fread(&arr[i], 1, sizeof(Person), fp);printf("写入了%d个字节的数据\n", count);printf("id=%d name=%s\n", arr[i].id, arr[i].name);}// 关闭文件fclose(fp);// 置空,释放内存fp = NULL;return 0;
}
输出:
写入了36个字节的数据
id=1 name=张三
写入了36个字节的数据
id=2 name=李四
写入了36个字节的数据
id=3 name=王五
fread一次性读取文件
#include <stdio.h>
#include <string.h>typedef struct person {int id;char name[32];
} Person;int main() {// 文件类型的指针FILE *fp = NULL;// 打开文件fp = fopen("test.txt", "r");// 判断是否打开成功if (fp == NULL) {printf("open failed!\n");return -1;}// 结构体数组Person arr[3];// 初始化内存memset(arr, 0, sizeof(arr));// 一次性读取文件fread(arr, 1, sizeof(arr), fp);// 读取文件for (int i = 0; i < 3; ++i) {printf("id=%d name=%s\n", arr[i].id, arr[i].name);}// 关闭文件fclose(fp);// 置空,释放内存fp = NULL;return 0;
}
输出:
id=1 name=张三
id=2 name=李四
id=3 name=王五
文件复制
基础示例
需求:将test.txt中的内容读取并写入到test2.txt中。
核心代码:
// 读取文件
int i;
char c[128];
double d;
fscanf(fp, "%d %s %lg\n", &i, c, &d);// 写入
fprintf(fp2,"%d %s %lg\n", i, c, d);
完整代码:
#include <stdio.h>int main() {// 文件类型的指针FILE *fp = NULL;FILE *fp2 = NULL;// 打开文件fp = fopen("test.txt", "r"); // r w a r+ w+ a+fp2 = fopen("test2.txt", "w");// 判断是否打开成功if (fp == NULL) {printf("open test.txt failed!\n");return -1;}if (fp2 == NULL) {printf("open test2.txt failed!\n");return -1;}// 读取文件int i;char c[128];double d;fscanf(fp, "%d %s %lg\n", &i, c, &d);// 写入fprintf(fp2,"%d %s %lg\n", i, c, d);// 关闭文件fclose(fp);fclose(fp2);// 置空,释放内存fp = NULL;fp2 = NULL;return 0;
}
fgetc和fputc
#include <stdio.h>int main() {// 文件类型的指针FILE *fp = NULL;FILE *fpw = NULL;// 打开文件fp = fopen("test.txt", "r");fpw = fopen("test2.txt", "w");// 判断是否打开成功if (fp == NULL) {printf("open test.txt failed!\n");return -1;}if (fpw == NULL) {printf("open test2.txt failed!\n");return -1;}char c;while (!feof(fp)) { // 使用feof判断文件末尾// 每次读一个字符c = fgetc(fp);if (c > 0) {// 每次写一个字符fputc(c, fpw);}};// 关闭文件fclose(fp);fclose(fpw);// 置空,释放内存fp = NULL;return 0;
}
feof 判断文件末尾
#include <stdio.h>int main() {// 文件类型的指针FILE *fp = NULL;FILE *fpw = NULL;// 打开文件fp = fopen("python.png", "rb");fpw = fopen("python2.png", "wb");// 判断是否打开成功if (fp == NULL) {printf("open python.png failed!\n");return -1;}if (fpw == NULL) {printf("open python2.png failed!\n");return -1;}char c;while (!feof(fp)) { // 使用feof判断文件末尾// 每次读一个字符c = fgetc(fp);// 每次写一个字符fputc(c, fpw);};// 关闭文件fclose(fp);fclose(fpw);// 置空,释放内存fp = NULL;return 0;
}
fgets和fputs
fgets和fputs读写文件效率更高,但是不能读写二进制文件,只能对文本文件有效。
#include <stdio.h>int main() {// 文件类型的指针FILE *fp = NULL;FILE *fpw = NULL;// 打开文件fp = fopen("test.txt", "r");fpw = fopen("test2.txt", "w");// 判断是否打开成功if (fp == NULL) {printf("open failed!\n");return -1;}if (fpw == NULL) {printf("open failed!\n");return -1;}// 按行读取字符串char *p = NULL;char buf[1024];// 循环读取while (1) {p = fgets(buf, sizeof(buf), fp);if (p == NULL) {break;}fputs(buf, fpw);}// 关闭文件fclose(fp);fclose(fpw);// 置空,释放内存fp = NULL;fpw = NULL;return 0;
}
练习:读写英语
每个练习可以独立为一个c文件,也可以合并
- 1、向english.txt中写入你最熟悉的四个英语语句,每行一个语句。
- 2、将english.txt中的内容编写代码复制到english2.txt中。
- 3、将english2.txt中的内容读取输出到stdout标准输出流中。
示例1:写入英语
#include <stdio.h>int main(){FILE* fp = fopen("english.txt", "w+");if (fp == NULL){printf("open the english.txt fail!\n");return -1;}printf("open the english.txt success!\n");fprintf(fp, "Hi, nice to meet you!\n");fprintf(fp, "I like english.\n");fprintf(fp, "How about you?\n");fprintf(fp, "Do you like to play basketball?\n");printf("write to english.txt success!\n");fclose(fp);fp = NULL;return 0;
}
示例2:复制文件
#include <stdio.h>int main(){FILE* r = fopen("english.txt", "r");if (r == NULL){printf("open english.txt fail!\n");return -1;}FILE* w = fopen("english2.txt", "w");if (w == NULL){printf("open english2.txt fail!\n");return -1;}char ch;while (1){ch = fgetc(r);if (ch == EOF){break;}fputc(ch, w);}printf("copy english.txt to english2.txt success!\n");fclose(r);r = NULL;fclose(w);w = NULL;return 0;
}
示例3:查看内容
#include <stdio.h>int main(){FILE* r = fopen("english2.txt", "r");if (r == NULL){printf("open english2.txt fail!\n");return -1;}char ch;while (1){ch = fgetc(r);if (ch == EOF){break;}fputc(ch, stdout);}fclose(r);r = NULL;return 0;
}
标准流
stdin 标准输入流
stdin用于从键盘上读取数据,也就是从控制台读取数据,是一种特殊的文件流。
示例代码:
#include <stdio.h>int main(){int n;fscanf(stdin, "%d", &n);fprintf(stdout, "%d\n", n);return 0;
}
输出:
11
11
stdout 标准输出流
可以将文件中读取的内容,输出到标准输出流中,也可以直接将内存中的内容输出到标准输出流中。
示例代码:
#include <stdio.h>int main(){char name[] = "zhangdapeng";fprintf(stdout, "%s\n", name);return 0;
}
输出:
zhangdapeng
stderr 标准错误流
标准错误流和标准输出流的用法是一样的,不过标准错误流一般用来输出错误信息。
示例代码:
#include <stdio.h>int main(){char errMsg[] = "Sorry, there is a panic error!!!";fprintf(stderr, "%s\n", errMsg);return 0;
}
输出:
Sorry, there is a panic error!!!