文件写入
基础示例
核心代码:
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!!!