一些简单的文件操作

文件的打开和关闭

要想实现该操作,我们要先了解两个函数,分别是fopen函数和fclose函数

fopen(打开文件)

fopen函数的声明

FILE * fopen ( const char * filename, const char * mode );
filename表示要打开的文件名称(可包含路径);mode 表示打开方式。

fopen函数的返回值

如果文件成功打开,该函数将返回指向 FILE 对象的指针,该对象可用于在将来的操作中标识流。
否则,将返回空指针

fclose(关闭文件)

fclose函数的声明

int fclose ( FILE * stream );
stream 指向指定要关闭的流的 FILE 对象的指针。

fclose函数的返回值

如果流成功关闭,则返回零值。
失败时,将返回 EOF。

绝对路径和相对路径

在进行文件操作时,我们先了解两个概念:绝对路径相对路径

绝对路径

假设有个文本文档的名称为“test.txt”,其存放在C盘的code文件夹中,即其路径为“C:\code\test.txt”,这个“C:\code\test.txt”就叫做绝对路径;

相对路径

若该文本文档与当前的项目在同一个目录中,那么其相对路径就是"test.txt";若该文本文档在该项目的上一个目录中,我们可以这样表示:“…/test.txt”,两个点表示上一个目录,三个点表示上上个目录,依次类推。

要注意,不同操作系统使用的斜杠不同,Linux系统是/,window系统是\

打开方式

这是fopen函数的第二个参数,如下

“r”(只读) 为了输入数据,打开一个已经存在的文本文件,如果指定文件不存在则出错
“w”(只写) 为了输出数据,打开一个文本文件,如果指定文件不存在则建立一个新的文件
“a”(追加) 向文本文件尾添加数据,如果指定文件不存在则建立一个新的文件
“rb”(只读) 为了输入数据,打开一个二进制文件,如果指定文件不存在则出错
“wb”(只写) 为了输出数据,打开一个二进制文件,如果指定文件不存在则建立一个新的文件
“ab”(追加) 向一个二进制文件尾添加数据,如果指定文件不存在则出错
“r+”(读写) 为了读和写,打开一个文本文件,如果指定文件不存在则出错
“w+”(读写) 为了读和写,建议一个新的文件,如果指定文件不存在则建立一个新的文件
“a+”(读写) 打开一个文件,在文件尾进行读写,如果指定文件不存在则建立一个新的文件
“rb+”(读写) 为了读和写打开一个二进制文件,如果指定文件不存在则出错
“wb+”(读写) 为了读和写,新建一个新的二进制文件,如果指定文件不存在则建立一个新的文件
“ab+”(读写) 打开一个二进制文件,在文件尾进行读和写,如果指定文件不存在则建立一个新的文件

代码实现

int main()
{
	//打开文件
	//FILE* pf = fopen("C:\\code\\test.txt", "r");
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");//如果错误则打印错误信息
		return 1;
	}
	else
	{
		printf("打开文件成功\n");
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

鼠标右击该项目的源文件,打开所在文件夹,在里面创建一个文本文档命名为"test.txt"
在这里插入图片描述
运行该代码,若打开文件成功,则有如下界面;若打开失败则会显示错误信息。
在这里插入图片描述

文件的顺序读写

同样的,在这之前我们先认识几个函数

fgetc(字符输入函数)

fgetc函数的声明

int fgetc ( FILE * stream );
stream指向标识输入流的 FILE 对象的指针

fgetc函数的返回值

成功后,将返回字符读取(提升为 int 值)。
返回类型为 int 以适应特殊值 EOF,该值表示失败

通过fgetc函数写文件

int main()
{
	//以只写的方式打开文件
	FILE* pf = fopen("test.txt", "w");
	//判断返回值
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//写文件
	fputc('a', pf);
	fputc('b', pf);
	fputc('c', pf);
	fputc('d', pf);
	fputc('e', pf);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

我们可以打开记事本观察,如下显示:
这是运行前的结果
在这里插入图片描述

这是运行后的结果
在这里插入图片描述
可以看到我们已经成功往文件中写入了文件。

通过fgetc函数读文件

int main()
{
	//以只读的方式打开文件
	FILE* pf = fopen("test.txt", "r");
	//判断返回值
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//读文件

	int ch = fgetc(pf);
	printf("%c ", ch);

	ch = fgetc(pf);
	printf("%c ", ch);

	ch = fgetc(pf);
	printf("%c ", ch);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

该文件里存放着abcde五个字符,我们读了三次,每次打印一个字符,打印出来的恰好就是abc
在这里插入图片描述

知道了写文件和读文件之后,我们再来看看如何写一行文件和读一行文件,同样的认识一下几个函数。

fputs(文本行输出函数)

fputs函数的声明

int fputs ( const char * str, FILE * stream );
str包含要写入流的内容的 C 字符串;stream指向标识输出流的 FILE 对象的指针。

fputs的返回值

成功时,将返回非负值
出错时,该函数返回 EOF 并设置错误指示器(ferror)。

通过fputs函数写一行文件

int main()
{
	//以只写的方式打开文件
	FILE* pf = fopen("test.txt", "w");
	//判断返回值
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//写一行文件
	fputs("hello world\n", pf);
	fputs("abcdef\n", pf);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

运行后记事本的内容如下,可以看到内容已经成功写入
在这里插入图片描述

fgets(文本行输入函数)

fgets函数的声明

char * fgets ( char * str, int num, FILE * stream );
str指向在其中复制字符串读取的字符数组的指针;
num表示要复制到 str 的最大字符数(包括终止空字符);
stream指向标识输入流的 FILE 对象的指针。

fgets函数的返回值

成功后,函数返回 str。
如果在尝试读取字符时遇到文件末尾,则设置 eof 指示器 (feof)。如果在读取任何字符之前发生这种情况,则返回的指针为空指针(str 的内容保持不变)。
如果发生读取错误,则设置错误指示器(ferror),并返回空指针(但str指向的内容可能已更改)。

通过fgets函数读一行文件

int main()
{
	//以只读的方式打开文件
	FILE* pf = fopen("test.txt", "r");
	//判断返回值
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//读一行文件
	char buf[20] = { 0 };
	fgets(buf, 20, pf);
	printf("%s", buf);

	fgets(buf, 20, pf);
	printf("%s", buf);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

运行结果如下,可以看到文件的内容成功地被输出到了屏幕上
在这里插入图片描述

二进制的输入和输出

主要包括以二进制地方式写入和读取文件,还是需要通过几个函数来实现

fwrite(写入要流式传输的数据块)

fwrite函数的声明

size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
ptr指向要写入的元素数组的指针;
size表示要写入的每个元素的大小(以字节为单位);
count表示元素数,每个元素的大小为字节大小;
stream指向指定输出流的 FILE 对象的指针。

fwrite函数的返回值

返回成功写入的元素总数。
如果此数字与 count 参数不同,则写入错误阻止函数完成。在这种情况下,将为流设置错误指示器(ferror)。
如果大小或计数为零,则该函数返回零,错误指示器保持不变。

通过fwrite以二进制的方式写文件

struct S
{
	char name[20];
	int age;
	float score;
};
int main()
{
	struct S s = { "zhangsan", 20, 95.5 };
	FILE* pf = fopen("test.txt", "wb");
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
	//以二进制的方式写文件
	fwrite(&s, sizeof(struct S), 1, pf);
	
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

运行后我们打开文本文档查看,结果是这样
在这里插入图片描述
其实这很正常,以为是以二进制的方式写入,我们可以这样查看:
首先在源文件处添加现有项
在这里插入图片描述
然后添加该文本文档
在这里插入图片描述
右击该新建项选择打开方式,接着
在这里插入图片描述
我们就可以看到二进制的编辑结果了
在这里插入图片描述

fread(从流中读取数据块)

fread函数的声明

size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
ptr指向大小至少为 (size*count) 字节的内存块的指针;
size表示要读取的每个元素的大小(以字节为单位);
count表示元素数,每个元素的大小为字节大小;
stream指向指定输入流的 FILE 对象的指针。

fread函数的返回值

返回成功读取的元素总数。
如果此数字与 count 参数不同,则表示读取时发生读取错误或到达文件末尾。在这两种情况下,都会设置正确的指标,可以分别用 ferror 和 feof 进行检查。
如果大小或计数为零,则该函数返回零,并且流状态和 ptr 指向的内容保持不变。

通过fread以二进制的方式读文件

struct S
{
	char name[20];
	int age;
	float score;
};
int main()
{
	struct S s = { "zhangsan", 20, 95.5 };
	FILE* pf = fopen("test.txt", "rb");
	if (NULL == pf)
	{
		perror("fopen");
		return 1;
	}
	//以二进制的方式读文件
	fread(&s, sizeof(struct S), 1, pf);
	printf("%s %d %f", s.name, s.age, s.score);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

结果如下
在这里插入图片描述
与我们写入文件中的结果一致。

文件的随机读写

fseek函数(重新定位流位置指示器)

fseek函数的声明

int fseek ( FILE * stream, long int offset, int origin );
stream指向标识流的 FILE 对象的指针;
offset表示要从源偏移的字节数;
origin用作偏移参考的位置;

其中origin由< cstdio >中定义的以下常量之一指定,专门用作此函数的参数

origin参考位置
SEEK_SET文件开头
SEEK_CUR文件指针的当前位置
SEEK_END文件结尾

fseek函数的返回值

如果成功,该函数将返回零。
否则,它将返回非零值。
如果发生读取或写入错误,则设置错误指示器(ferror)。

代码实现

我们先把文本文档里写入abcde的内容,如图
在这里插入图片描述
当我们关掉该文档再打开时,就变成了这样
在这里插入图片描述
它两的区别在于光标,其实fseek说白了就是控制该光标的位置

int main()
{
	FILE*pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
	}
	else
	{
		int ch = fgetc(pf);
		printf("%c\n", ch);//a
		ch = fgetc(pf);
		printf("%c\n", ch);//b
		ch = fgetc(pf);
		printf("%c\n", ch);//c
	}

	return 0;
}

打印出来的结果如下
在这里插入图片描述
每次fgets后光标默认向后移动一个,如果继续往下读,必然是打印d,但是我们可以通过fseek函数控制它,让它去打印b,我们可以这样写

fseek(pf, -2, SEEK_CUR);//表示从当前位置向左偏移两位

也就是从

在这里插入图片描述
变成
在这里插入图片描述
从而打印b,或者我们也可以这样写

fseek(pf, 1, SEEK_SET);//表示从起始位置向右偏移一位

同样是打印b
有时候我们不知道偏移量是多少,我们可以通过ftell函数计算偏移量,用法很简单;还可以通过rewind函数将文件指针恢复到起始位置,用法同样很简单。

int main()
{
	FILE*pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
	}
	else
	{
		int ch = fgetc(pf);
		printf("%c\n", ch);
		ch = fgetc(pf);
		printf("%c\n", ch);
		ch = fgetc(pf);
		printf("%c\n", ch);
		
		fseek(pf, 1, SEEK_SET);
		ch = fgetc(pf);
		printf("%c\n", ch);
		
		printf("%d\n", ftell(pf));
		rewind(pf);
		ch = fgetc(pf);
		printf("%c\n", ch);
	}

	return 0;
}

以上代码运行的结果如下,首先打印abc,调整偏移量后打印b,然后计算此时的偏移量为2,最后通过rewind函数将文件指针恢复到起始位置,从而打印a。
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值