C语言--(十 二)(Lellansin) 文件操作

本文详细介绍了C语言中文件操作的基本概念,包括FILE结构体的使用,文件的打开与关闭,读取与写入一行数据的方法,以及如何设置和获取文件位置。通过具体的代码示例,展示了fopen(), fclose(), fgets(), fputs(), fseek()和ftell()等函数的应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录:

一 : FILE结构体

二 :获取文件 fopen()、fclose() :

三 :获取一行fgets(): 

四 :写入一行fputs():

五 :设置位置fseek()、 获取当前位置ftell()

六 :小结

七 :作业

一、FILE 结构体:

struct _iobuf {
    char *_ptr;
    int _cnt;
    char *_base;
    int _flag;
    int _file;
    int _charbuf;
    int _bufsiz;
    char *_tmpfname;
    };
tpyedef struct _iobuf FILE;

正常情况下,我们使用的都是FILE结构体的指针

二、获取文件 fopen()、fclose() :
 功能:打开 关闭文件

1 fopen():

原型:

FILE * fopen(const char *path, const char *mode);

第一个参数: path 读取文件路径

第二个参数: mode 文件使用的模式

常见模式(mode):

read 读
write 写
addit 附加

返回值 是一个FILE结构体的地址

2 fclose() :

fclose() 则是将文件结构体指针传入,然后释放改文件,情况类似free()函数

三、fgets():

读取相应的文件,类似gets() 函数一次读取一行

原型:

char *fgets(char *buf, int bufsize, FILE *stream);

第一个参数: buf 缓冲缓存

第二个参数: bufsize 知名前面的大小

第三个参数: stream file结构体,在这里对其操作

#include<stdio.h>

int main() {
    FILE *fp;
    char buf[20];
    fp = fopen("E:\\1.txt", "r");
    fgets(buf, 20, fp);
    printf(buf);
    return 0;
}

PS: 关于路径写法问题  windows的路径是\\,ubuntu是/   

https://blog.youkuaiyun.com/zjc910997316/article/details/84405031


 

#include<stdio.h>
#include<windows.h>

int main() {
	FILE *fp;  // FILE结构体
	char buf[20];

    // 打开文件
	fp = fopen("H:\\(VS)2012\\Archer_project\\Test1\\1.txt", "r");  // r 只读模式

	if (fp == NULL) {
		printf("打开文件失败");
	}
    
    // 获取文件
	fgets(buf, 20, fp);
	printf("%s", buf);

    // 关闭文件
	fclose(fp);
	
	Sleep(10000);
	
}

如果1.txt 文件里面是

hello world 

hi alan

只能获取一行

如下即可获取第二行:

#include<stdio.h>
#include<windows.h>

int main() {
	FILE *fp;  // FILE结构体
	char buf[20];

    // 打开文件
	fp = fopen("H:\\(VS)2012\\Archer_project\\Test1\\1.txt", "r");  // r 只读模式

	if (fp == NULL) {
		printf("打开文件失败");
	}
    
    // 获取文件
	fgets(buf, 20, fp);
	printf("%s", buf);

    // 获取文件 第二行
	fgets(buf, 20, fp);
	printf("%s", buf);

    // 关闭文件
	fclose(fp);
	
	Sleep(10000);
	
}

同理,使用多次,可以获取多行

循环读取:

下面是循环读取,直到没有

#include<stdio.h>
#include<windows.h>

int main() {
	FILE *fp;  // FILE结构体
	char buf[20];

    // 打开文件
	fp = fopen("H:\\(VS)2012\\Archer_project\\Test1\\1.txt", "r");  // r 只读模式

	if (fp == NULL) {
		printf("打开文件失败");
	}
    
    // 获取文件
    while(fgets(buf, 20, fp)) {  // 如果读到结尾会返回一个空,这样就不会继续再读取
	printf("%s", buf);

    }

    // 关闭文件
	fclose(fp);
	
	Sleep(10000);
	
}

宏定义:

定义一个宏定义,随时来改变buf size大小

#include<stdio.h>
#include<windows.h>
#define BUFSIZE 20  // 宏定义 


int main() {
	FILE *fp;  
	char buf[ BUFSIZE ];  // 宏定义 

    // 打开文件
	fp = fopen("H:\\(VS)2012\\Archer_project\\Test1\\1.txt", "r");  
	if (fp == NULL) {
		printf("打开文件失败");
	}
    
    // 获取文件
    while(fgets(buf,  BUFSIZE , fp)) {   // 宏定义 
	printf("%s", buf);

    }

    // 关闭文件
	fclose(fp);
	
	Sleep(10000);
	

四、fputs():

写入相应的文件,类似puts()函数,一次写一行

原型:

int fputs(char *str, FILE *fp);

#include<stdio.h>

int main() {
    FILE *fp;
    char buf[20] = "hello world";
    fp = fopen("E:\\1.txt", "w");
    fputs(buf, fp);
    return 0;
}

一次写入一行

 

把 buf[BUFSIZE] 里面的内容写入到 1.txt 文件里面:

#include<stdio.h>
#include<windows.h>
#define BUFSIZE 52 

int main() {
	FILE * f;
	char buf[BUFSIZE] = "This is fputs function! \nhello fputs!";
	f = fopen("C:\\1.txt", "w");
	if (NULL ==f) {  // ==是比较, =是赋值。NULL == f这样写可以避免写错成NULL = f,因为NULL常值不会被赋值
		printf("write file failed!");
	}
	fputs(buf, f);
	fclose(f);
}

成功写入

五、fseek()、 ftell()

fseek() 设置文件位置

ftell()     获取当前位置

int fseek(FILE *stream, long offset, int fromwhere);

第一个参数 是要操作的文件流指针(即文件结构体

第二个参数 偏移量

第三个参数 偏移的相对的位置 , 针对什么地方的偏移

 

常见的位置有:
SEEK_SET: 文件开头
SEEK_CUR: 当前位置
SEEK_END: 文件结尾

ftell()的原型:

long ftell(FILE *stream);

通过文件结构体指针获取当前指向的位置

 

fgets():

#include<stdio.h>
#include<windows.h>
#define BUFSIZE 100

int main() {
	FILE *fp;  // FILE结构体
	char buf[BUFSIZE];

    // 打开文件
	fp = fopen("C:\\1.txt", "r");  // r 只读模式

	if (fp == NULL) {
		printf("打开文件失败");
	}
    
    // 获取文件
	fgets(buf, BUFSIZE, fp);
	printf("%s\n", buf);

	fseek(fp, 0, SEEK_SET);  // 前面虽然读过第一行了,这个函数从新置到起始位置,把第一行又读一遍

	fgets(buf, BUFSIZE, fp);
	printf("%s\n", buf);
	

    // 关闭文件
	fclose(fp);
	
	Sleep(10000);
	
}

 

注释掉fseek()

#include<stdio.h>
#include<windows.h>
#define BUFSIZE 100

int main() {
	FILE *fp;  // FILE结构体
	char buf[BUFSIZE];

    // 打开文件
	fp = fopen("C:\\1.txt", "r");  // r 只读模式

	if (fp == NULL) {
		printf("打开文件失败");
	}
    
    // 获取文件
	fgets(buf, BUFSIZE, fp);
	printf("%s\n", buf);

	//fseek(fp, 0, SEEK_SET);

	fgets(buf, BUFSIZE, fp);
	printf("%s\n", buf);
	

    // 关闭文件
	fclose(fp);
	
	Sleep(10000);
	
}

如果设置为5偏移量,从第五个开始读

#include<stdio.h>
#include<windows.h>
#define BUFSIZE 100

int main() {
	FILE *fp;  // FILE结构体
	char buf[BUFSIZE];

    // 打开文件
	fp = fopen("C:\\1.txt", "r");  // r 只读模式

	if (fp == NULL) {
		printf("打开文件失败");
	}
    
    // 获取文件
	fgets(buf, BUFSIZE, fp);
	printf("%s\n", buf);

	fseek(fp, 5, SEEK_SET);

	fgets(buf, BUFSIZE, fp);
	printf("%s\n", buf);
	

    // 关闭文件
	fclose(fp);
	
	Sleep(10000);
	
}

SEEK_END

相对于结尾来偏移

#include<stdio.h>
#include<windows.h>
#define BUFSIZE 100

int main() {
	FILE *fp;  // FILE结构体
	char buf[BUFSIZE];

    // 打开文件
	fp = fopen("C:\\1.txt", "r");  // r 只读模式

	if (fp == NULL) {
		printf("打开文件失败");
	}
    
    // 获取文件
	fgets(buf, BUFSIZE, fp);
	printf("%s\n", buf);

	fseek(fp, -5, SEEK_END);  // 相对于结尾来偏移

	fgets(buf, BUFSIZE, fp);
	printf("%s\n", buf);
	

    // 关闭文件
	fclose(fp);
	
	Sleep(10000);
	
}

输出文件最后五个字符

六、小结

 

 (这里是不是写反了? 答案是:没)

一。基本操作

1.FILE 文件结构体

2.fopen()文件的打开

3.fclose() 文件的关闭

 

fopen()文件的打开:

r      读

r+    读的同时可以写,

w+    写的同时可以读, 

r+ w+区别:
r+  去读取位置去读文件,如果没有文件一定读不到。
w+ 写的同时去读,如果读不到,就会自己去创建这个文件

 

二。文件读写

1.fget()文件读取 读文件,读完一行,指针会下移动,如果buf没读完一行,此次在读取就会从没读完的位置继续读
2.fputs()文件写入

三。文件位置操作

1.ftell() 获取当前文件操作的位置
2.fseek() 设置文件操作的位置 

七、作业

r模式 需要有事先准备好的文件,所以1.txt, 2.txt需要提前写好

w模式 会自动创建文件,因此3.txt, 4.txt, 5.txt都不需要提前创建

1.txt, 2.txt的文件分别是

提前准备1.txt:

i
ii
iii

要注意多回车一行,
不然后面do{}while(now!=flag)将会无法成立,
可以改成do{}while( flag > now);来实现

do {  // 写入4.txt
        fgets(buf, 100, fp3);
        fputs(buf, fp_cut1); 
        printf("%s", buf);
        now = ftell(fp3);
        //printf("flag is %long", flag);
        //printf("now is %long", now);
        //Sleep(10000);
        //i++;
    } while( flag > now);

提前准备2.txt:


o
oo
ooo

这里不需要回车,

但是前面留空行,这样看着更方便~

完整代码:

#include<stdio.h>
#include<windows.h>

int main() {
	FILE *fp1, *fp2, *fp3, *fp_w;  // FILE结构体
	FILE *fp_cut1, *fp_cut2;
	char buf[100];
	long flag, now;  // flag用于标记位置,now记录fp3当前位置
 
    // 打开文件
	fp1 = fopen("C:\\1.txt", "r");  // r 只读模式
	fp2 = fopen("C:\\2.txt", "r");  // r 只读模式
	fp_w = fopen("C:\\3.txt", "w");

	// 第一部分fp1: 读取1.txt写入3.txt
	if (fp1 == NULL) {
		printf("1.txt打开文件失败");
	}
	printf("下面是1.txt内容:\n");
	while ( fgets(buf, 100, fp1) ) {  // 直到读不到停止
		printf("%s", buf);
		fputs(buf, fp_w);  // 写入
	}
	
	//记录在3.txt中的位置
	flag = ftell(fp_w);
	printf("\n\n标记位置为:%lon\n", flag);
	
	// 第二部分fp2: 读取2.txt写入3.txt
	if (fp2 == NULL) {
		printf("2.txt打开文件失败");
	}
	printf("\n下面是2.txt内容:\n");
	while ( fgets(buf, 100, fp2) ) {  // 直到读不到停止
		printf("%s", buf);
		fputs(buf, fp_w);  // 写入
	}
	fclose(fp_w); // fp_w: 通过关掉fp_w关掉文件3.txt,才能在下面fp3再次打开
	//Sleep(10000);


	// 第三部分fp3: 读取3.txt展示出来
	fp3 = fopen("C:\\3.txt", "r");  // r 只读模式
 
	if (fp3 == NULL) {
		printf("3.txt打开文件失败");
	}
	printf("\n\n下面是3.txt内容:\n");
    while(fgets(buf, 100, fp3)) {  // 如果读到结尾会返回一个空,这样就不会继续再读取
		printf("%s", buf);
    }

	// 第四部分fp_cut1: 把3.txt中flag标记前面的内容写入4.txt
	printf("\n\n下面是4.txt内容:\n");
	fseek(fp3, 0, SEEK_SET);  // 3.txt中标记开头
	fp_cut1 = fopen("C:\\4.txt", "w");
	do {  // 写入4.txt
		fgets(buf, 100, fp3);
		fputs(buf, fp_cut1); 
		printf("%s", buf);
		now = ftell(fp3);
		//printf("flag is %long", flag);
		//printf("now is %long", now);
		//Sleep(10000);
		//i++;
	} while( flag != now);  

	printf("\nflag is %long", flag);
	printf("\nnow is %long", now);
	
	// 第五部分fp_cut2: 把3.txt中flag标记后面的内容写入5.txt
	printf("\n\n下面是5.txt内容:\n");
	fseek(fp3, flag, SEEK_SET);  // 3,txt中标记开头
	fp_cut2 = fopen("C:\\5.txt", "w");
	while(fgets(buf, 100, fp3)) {  
		fputs(buf, fp_cut2);  // 写入5.txt
		printf("%s", buf);
	} 

    // 关闭文件
	fclose(fp1);
	fclose(fp2);
	fclose(fp3);
	
	fclose(fp_cut1);
	fclose(fp_cut2);
	
	Sleep(10000);
}

’结果:

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

计算机视觉-Archer

图像分割没有团队的同学可加群

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值