C语言之文件顺序读写和随机读写

上篇博客介绍了文件的基本知识,本文将详细讲解有关文件顺序读写和随机读写函数。

一、文件的顺序读写

在C语言中,文件的顺序读写指的是按照文件中的顺序来读取或写入数据,下面是常用到的函数。

功能

函数名

适用于

字符输入函数

fgetc

所有输入流

字符输出函数

fputc

所有输出流

文本行输入函数

fgets

所有输入流

文本行输出函数

fputs

所有输出流

格式化输入函数

fscanf

所有输入流

格式化输出函数

fprintf

所有输出流

二进制输入

fread

文件

二进制输出

fwrite

文件

1.1 fgetc()和fputc()函数

fgetc 和 fputc 函数分别用于从文件中读取一个字符和向文件中写入一个字符。这两个函数都是标准I/O库中的一部分,提供了对文件字符级操作的能力。

1.1.1 fgetc()

int fgetc( FILE *stream );

fgetc 函数用于从指定的文件流中读取下一个字符(一个无符号字符),并将其作为 int 类型的值返回。如果到达文件末尾(EOF)或发生错误,则返回 EOF。注意,EOF 是一个在 <stdio.h> 中定义的宏,通常是一个负值,用于指示文件结束或读取错误。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

int main()
{
	FILE* pf = fopen("text.txt", "r");//打开已经创建好的文件
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//读文件
	int ret = fgetc(pf);
	printf("%c\n", ret);
	ret = fgetc(pf);
	printf("%c\n", ret);
	ret = fgetc(pf);
	printf("%c\n", ret);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

2f17963cd0154342912f28b7d41bf7a5.png

e80fc49847364ec7be0bdf2e7deefc57.png

1.1.2 fputc()

 int fputc( int c, FILE *stream );

fputc 函数用于将一个字符写入到指定的文件流中。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

int main()
{
	FILE* pf = fopen("text.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//写文件
	fputc('f', pf);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

59161d72731b42459e758d96967d0025.png

1.2 fgets()和fputs()函数

1.2.1 fputs()

int fputs( const char *string, FILE *stream );

fputs 函数用于将字符串写入到指定的文件流中,但不包括空字符 \0。如果成功,它返回非负值;如果发生错误,则返回 EOF

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

int main()
{
	FILE* pf = fopen("text.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//写文件-行
	fputs("abcde\n", pf);
	fputs("fgh\n", pf);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

95db9edc0adf4f429e903f5f7df07681.png

1.2.2 fgets()

fgets 函数用于从指定的文件流中读取一行文本(包括换行符,如果有的话,但最多读取到数组大小减一的位置),并将其存储在字符串中。如果成功,它会返回一个指向该字符串的指针;如果发生错误或到达文件末尾(EOF)而没有读取任何字符,则返回 NULL

char *fgets( char *string, int n, FILE *stream );

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

int main()
{
	char arr[10] = { 0 };
	FILE* pf = fopen("text.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//读文件
	fgets(arr, 4, pf);
	printf("%s\n", arr);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

23baa2cf5c83449a839079078c319445.png

1.3 fprintf()和fscanf()函数

1.3.1 fprintf()

fprintf 函数用于向指定的输出流(如文件)写入格式化的数据。

int fprintf( FILE *stream, const char *format [, argument ]...);

stream 是指向 FILE 对象的指针,该对象标识了要写入数据的输出流。

format 是一个格式字符串,指定了后续参数(...)如何写入到输出流中。这个格式字符串与 printf 函数的格式字符串非常相似。

后续参数(...)是要写入输出流的数据。

fprintf 函数返回写入的字符数(不包括终止的空字符),如果发生错误,则返回负数。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

struct S
{
	char arr[10];
	int num;
	float sc;
};

int main()
{
	struct S s = { "abcde",10,5.5f };
	//对格式化的数据进行写文件
	FILE *pf= fopen("text.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//写文件
	fprintf(pf, "%s %d %f", s.arr, s.num, s.sc);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

 

1.3.2 fscanf() 

fscanf 函数用于从指定的输入流(如文件)中按照指定格式读取数据。

int fscanf( FILE *stream, const char *format [, argument ]... );

stream 是指向 FILE 对象的指针,该对象标识了要从中读取数据的输入流。

format 是一个格式字符串,指定了后续参数(...)的读取方式。这个格式字符串与 scanf 函数的格式字符串非常相似。

后续参数(...)是指向变量的指针,这些变量用来存储从输入流中读取的数据。

fscanf 函数返回成功读取的项目数,如果到达文件末尾或发生读取错误,则返回 EOF

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

struct S
{
	char arr[10];
	int num;
	float sc;
};

int main()
{
	struct S s = {0};
	//对格式化的数据进行读文件
	FILE* pf = fopen("text.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//读文件
	fscanf(pf, "%s %d %f", s.arr, &(s.num ), &(s.sc));
	//打印
	printf("%s %d %f\n", s.arr, s.num, s.sc);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

1.4 fread()和fwrite()函数

1.4.1 fwrite()

fwrite 函数用于向文件写入数据块。

size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );

buffer 指向要写入的数据块的指针。

size 是每个数据项的大小(以字节为单位)。

count 是数据项的数量。

stream 是指向 FILE 对象的指针,该对象标识了要写入数据的输出流。

fwrite 返回成功写入的项数,如果发生错误,则返回小于count的值。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

struct S
{
	char arr[10];
	int num;
	float sc;
};
int main()
{
	struct S s = { "abc",10,5.5f };
	//二进制的形式写
	FILE* pf = fopen("text.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//写文件
	fwrite(&s, sizeof(struct S), 1, pf);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

由于是以二进制的形式写入的,所以看不懂很正常。

1.4.2  fread()

fread 函数用于从文件流中读取数据。这个函数可以非常灵活地从文件中读取指定数量的元素,每个元素具有指定的大小(以字节为单位)。这使得 fread 成为处理二进制文件或需要精确控制读取数据量时非常有用的工具。

size_t fread( void *buffer, size_t size, size_t count, FILE *stream );

void *buffer:指向一个数组的指针,该数组用于存储从文件读取的数据。

size_t size:每个数据项的大小,以字节为单位。

size_t count:要读取的数据项的最大数量。

FILE *stream:指向 FILE 对象的指针,该对象标识了要从中读取数据的输入流。

成功时,fread 返回实际读取的元素数量,这可能会少于请求的数量(例如,如果到达文件末尾或发生错误)。

如果发生错误或到达文件末尾而没有读取任何数据,则返回 0

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

struct S
{
	char arr[10];
	int num;
	float sc;
};
int main()
{
	struct S s = {0};
	//二进制的形式读
	FILE* pf = fopen("text.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//读文件
	fread(&s, sizeof(struct S), 1, pf);
	//打印
	printf("%s %d %f\n", s.arr, s.num, s.sc);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

 

二、 几种函数对比

2.1 函数

scanf:针对标准输入的格式化的输入语句

fscanf:针对所有输入流的格式化的输入语句

sscanf:从一个字符串中读取一个格式化的数据

printf:针对标准输出的格式化的输出语句

fprintf:针对所有输出流的格式化的输出语句

sprintf:把一个格式化的数据转换成字符串

以下是sscanf和sprintf函数的函数原型:

int sscanf( const char *buffer, const char *format [, argument ] ... );

int sprintf( char *buffer, const char *format [, argument] ... );

2.2 代码示例

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

struct S
{
	char arr[10];
	int age;
	float f;
};
int main()
{
	struct S s = { "hello",20,5.5f };
	struct S temp = { 0 };
	char buf[100] = { 0 };
	//sprintf 把一个格式化的数据转换成字符串
	sprintf(buf, "%s %d %f", s.arr, s.age, s.f);
	printf("%s\n", buf);
	//从buf字符串中还原出一个结构体数据
	sscanf(buf, "%s %d %f", temp.arr, &temp.age, &temp.f);
	printf("%s %d %f\n", temp.arr, temp.age, temp.f);
	return 0;
}

 

三、文件的随机读写

在C语言中,进行随机读写操作(即不是顺序地从文件开头或结尾读写,而是根据文件内的特定位置进行读写)时,主要依赖几个标准的文件操作函数,特别是那些允许你移动文件指针到文件中的特定位置的函数。

3.1 fseek()

fseek()函数用于将文件内的位置指示器(即文件指针)移动到指定的位置。

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

stream 是指向 FILE 对象的指针,该对象标识了要操作的文件。

offset 是从 whence 指定的位置开始计算的偏移量,以字节为单位。

origin是起始位置,可以是 SEEK_SET(文件开头),SEEK_CUR(当前位置),或 SEEK_END(文件末尾)。

文件中已经预先存入abcdef

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

int main()
{
	FILE* pf = fopen("text.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//读取文件
	int ch = fgetc(pf);
	printf("%c\n", ch);//a
	//调整文件指针
	fseek(pf, 2, SEEK_CUR);
	ch = fgetc(pf);
	printf("%c\n", ch);//d
	ch = fgetc(pf);
	printf("%c\n", ch);//e
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

3.2 ftell()

返回文件指针相对于起始位置的偏移量。

long ftell( FILE *stream );

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

int main()
{
	FILE* pf = fopen("text.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//读取文件
	int ch = fgetc(pf);
	printf("%c\n", ch);//a
	//调整文件指针
	fseek(pf, -2, SEEK_END);
	ch = fgetc(pf);
	printf("%c\n", ch);//e
	ch = fgetc(pf);
	printf("%c\n", ch);//f
	int ret = ftell(pf);
	printf("%d\n", ret);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

3.3 rewind()

让文件指针的位置回到文件的起始位置。

void rewind( FILE *stream );

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

int main()
{
	FILE* pf = fopen("text.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//读取文件
	int ch = fgetc(pf);
	printf("%c\n", ch);//a
	//调整文件指针
	fseek(pf, -2, SEEK_END);
	ch = fgetc(pf);
	printf("%c\n", ch);//e
	ch = fgetc(pf);
	printf("%c\n", ch);//f
	int ret = ftell(pf);
	printf("%d\n", ret);
	//让文件指针回到起始位置
	rewind(pf);
	ch = fgetc(pf);
	printf("%c\n", ch);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值