C语言:文件操作:顺序读写、随机读写

1. 文件顺序读写

  1. 使用需要先打开文件信息区File,File是指针类型,不同编译器的实现法不一样。通过文件指针变量,可以找到与它关联的文件。
  2. 基本使用:fopen打开,fclose关闭,mode规定打开文件方式,读、取。当打开某文件时,会先创建一个该文件信息区,fopen会返回文件信息的起始地址。

步骤:打开、读取、关闭

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>

int main()
{
	FILE* pf = fopen("E:\\C++workspace\\bite_learn\\L1\\Project1\\Project1\\test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen ERROR");
		return 1;
	}
	// 读取
	//fopen(pf);
	// 关闭
	fclose(pf);
	return 0;
}

注意:1. 文件路径中,必须是双\,且mode选的"r",目录下要有text文件,没有则会报错。但是如果选择"w"模式,则会创建
2. 先判断了是否打开这片区,下面才是读取
3: 文件使用方式:r、w、a:只读、只写、追加

3. 写文件案例:利用fputc():针对所有输出流,fgetc()针对所有输入流
分析:必然是w模式,且写入用fputc()函数

int main()
{
	FILE* pf = fopen("E:\\C++workspace\\bite_learn\\L1\\Project1\\Project1\\test_write.txt", "w");
	if (pf == NULL)
	{
		perror("fwrite ERROR");
		return 1;
	}
	char ch = 'a';
	for (;ch<='z'; ch++)
	{
		fputc(ch, pf);
	}
	// 读取
	
	//fopen(pf);
	
	// 关闭

	fclose(pf);
	return 0;
}

4. 读文件案例:利用fgetc(),遇到末尾或者错误,会返回EOF,所以以EOF判断

int main()
{
	FILE* pf = fopen("E:\\C++workspace\\bite_learn\\L1\\Project1\\Project1\\test_write.txt", "r");
	if (pf == NULL)
	{
		perror("fwrite ERROR");
		return 1;
	}
	/*char ch = 'a';
	for (;ch<='z'; ch++)
	{
		fputc(ch, pf);
	}*/
	// 读取
	int ch = 0;
	while ((ch = fgetc(pf)) != EOF)
	{
		printf("%c ", ch);
	}

	// 关闭
	fclose(pf);
	pf = NULL;
	return 0;
}

5 流:外部设备不一样,操作外部设备读写方法也不一样,把字符都放在流中,程序员关注从流中读写,不用在意外部设备,其实上面pf就是流。
stdin、stdout、stderr:C程序运行起来,这三个流默认是打开的
在和不同外设交互时这些流都有用
单个读、单个写:都用fgetc、fputc

stdin针对所有输入流,stdout针对所有输出流

示例代码:

int ch = fgetc(stdin);
fputc(ch, stdout);

单行读、单行写:fputs、fgets,如果要换行,加上\n

	FILE* pf = fopen("test1.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	// 写一行
	fputs("qwerty", pf);
	// 关闭
	fputs("abcdef", pf);

	return 0;
}

结果:
请添加图片描述
没有换行,写入的时候,需要加\n
· 按一行行重复读取:while:fgets返回不为空
多行读取:需要接收的字符数组,接收长度,文件流

char arr[256] = { 0 };
	while (fgets(arr, 256, pf)!=NULL)
	{
		printf("%s", arr);
	}

结果:
请添加图片描述
到目前为止,应该学会了如下4个函数的使用:
请添加图片描述

  • fprintf():格式化输出流,写结构体到文件中,方便控制写入格式,如下结构体写入文件做规定。
// 写文件
fprintf(pf, "%s %d %lf", s.name, s.agem, s.d)
// 关闭文件
fclose(pf)
pf = NULL;
return 0;

如上,实现了结构体中内容存入了文件,下面实现从文件中读取到结构体中
注意是百分号爱了F,不是单纯F,是LF,代表double

// 读文件	name是数组,名字就是地址,age和d是变量,需要取地址
	struct stu
	{
		char name[20];
		int age;
		double d;
	};
	struct stu s = {0};
	FILE* pf = fopen("test1.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	// 写文件
	//fprintf(pf, "%s %d %1f", s.name, s.age, s.d);
	
	// 读文件	name是数组,名字就是地址,age和d是变量,需要取地址
	fscanf(pf, "%s %d %lf", s.name, &(s.age), &(s.d));
	// 打印:
	printf("%s %d %lf\n", s.name, s.age, s.d);
	// 关闭
	fclose(pf);
	pf = NULL;
	return 0;
}

总之,先读出来,再打印,也可以用fprintf,给stdout

fscanf(pf, "%s %d %lf", s.name, &(s.age), &(s.d));
// 打印:
//printf("%s %d %lf\n", s.name, s.age, s.d);
fprintf(stdout, "%s %d %lf\n", s.name, s.age, s.d);
// 关闭

所以说,fprintf()可以用在打印文件内,也可以用来输出到文件中

sprintf、sscanf的使用
sprintf把结构体数据存入字符串中,sscanf可以从读取字符串中数据到结构体
示例

char buf[256] = { 0 };
	struct S s = { "zhangsan", 20, 95.5 };
	struct S tmp = { 0 };
	sprintf(buf, "%s %d %lf", s.name, s.age, s.d);
	printf("%s\n", buf);
	sscanf(buf, "%s %d %lf", tmp.name, &(tmp.age), &(tmp.d));
	printf("%s %d %lf", tmp.name, tmp.age, tmp.d);

请添加图片描述
从输入流读字符,再打印到输出流
fgetc和fputc适用于所有输入流和输出流

int ch = fgetc(stdin);
fputc(ch, stdout);
return 0;

以二进制形式写进去会乱码
张三以二进制和文本方式写,都是张三,但是数字以二进制形式,以文本形式打开,显示是乱码。

struct S s = { "张三", 20, 95.5 };
	// 写文件,二进制方式 write_brinary
	fopen("test3.txt", "wb");
	FILE* pf = fopen("test3.txt", "wb");
	if (pf == NULL)
	{
		perror("fopen\n");
		return 1;
	}
	// 二进制方式写文件
	fwrite(&s,sizeof(struct S), 1, pf);
	// 关闭文件
	fclose(pf);
	pf = NULL;
	return 0;

请添加图片描述

需以二进制方式读文件

int main()
{
	struct S s = { "张三", 20, 95.5 };
	// 写文件,二进制方式 write_brinary
	fopen("test3.txt", "rb");
	FILE* pf = fopen("test3.txt", "wb");
	if (pf == NULL)
	{
		perror("fopen\n");
		return 1;
	}
	// 二进制方式写文件
	//fwrite(&s,sizeof(struct S), 1, pf);
	
	// 二进制读文件 
	fread(&s, sizeof(struct S), 1, pf);
	printf("%s, %d, %lf\n", s.name, s.age, s.d);
	// 关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

请添加图片描述
这里发现,txt文件本来看着是乱码,现在读出来是正常情况。
不管是读还是写,第三个参数:1、2是最多读取几次

4. 文件随机读写

1. fseek
使用规则:origin:文件指针当前位置
请添加图片描述

int main()
{
	// 打开文件
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	// 随机写

	// 正常读, 现在读到的是第一个字符
	//int ch = fgetc(pf);
	//printf("%c\n", ch);

	// 随机读
	fseek(pf, 3 SEEK_CUR);
	int ch = fgetc(pf);
	printf("%c\n", ch);

	// 关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

fseek中是3,表示从3开始,
发现读出来的是d,test文件中,我是abcde
所以运行结果是:
请添加图片描述

3. 写文件本质

文件缓冲区的存在:
写文件,先写入缓冲区,刷新缓冲区,才将缓冲区文件,写入文件。

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值