文件操作 读写

3-范天祚
3-范天祚   编辑于 2018-12-21 09:27
阅读量: 208

谢谢老师的修改和建议。

1 文件处理原理及基本概念

C语言的文件处理功能,大体上分为两种:一种是设置缓冲区,另一种是不设置缓冲区。因为不设置缓冲区的方法直接对磁盘进行操作,速度较慢,并且由于不是C的标准函数,跨平台操作时容易出问题。本文只介绍设置缓冲区的文件处理方式:

当使用包含在头文件stdio.h中的标准I/O函数时,系统会自动设置缓冲区,并通过数据流来读写文件。当进行文件读取时,不会直接对磁盘进行读取,而是先打开数据流,将磁盘上的文件信息拷贝到缓冲区内,然后程序再从缓冲区中读取所需数据。

 

1.1 相关概念

 

数据流:指程序与数据的交互是以流的形式进行的。进行C语言文件的存取时,都会先进行“打开文件”操作,这个操作就是在打开数据流,而“关闭文件”操作就是关闭数据流。

缓冲区:指在程序执行时,所提供的额外内存,可用来暂时存放做准备执行的数据。它的设置是为了提高存取效率,因为内存的存取速度比磁盘驱动器快得多。

1.2 文件类型

介绍下文本文件和二进制文件,

文本文件:是以字符编码的方式进行保存的。

二进制文件:将内存中数据原封不至文件中,如果以记事本打开,只会看到一堆乱码。二进制文件的优点在于存取速度快,占用空间小,以及可随机存取数据。

2 文件操作函数

2.1 打开文件

您可以使用 fopen( ) 函数来创建一个新的文件或者打开一个已有的文件,这个调用会初始化类型 FILE 的一个对象,类型 FILE 包含了所有用来控制流的必要的信息。下面是这个函数调用的原型:

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

filename 是字符串,代表文件名。Mode为文件的打开模式。何为打开模式?下面列出:

r

打开一个已有的文本文件,允许读取文件。

w

打开一个文本文件,允许写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会从文件的开头写入内容。如果文件存在,则该会被截断为零长度,重新写入。

a

打开一个文本文件,以追加模式写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会在已有的文件内容中追加内容。

r+

打开一个文本文件,允许读写文件。

w+

打开一个文本文件,允许读写文件。如果文件已存在,则文件会被截断为零长度,如果文件不存在,则会创建一个新文件。

a+

打开一个文本文件,允许读写文件。如果文件不存在,则会创建一个新文件。读取会从文件的开头开始,写入则只能是追加模式。

注:打开二进制文件的模式与打开文本文件是一样的,不同的是模式名称里面多一个字母'b’,以表示以二进制形式打开文件。

举例说明:

FILE *fp = NULL;

fp = fopen("/tmp/test.txt", "w+");

2.2 关闭文件

关闭文件,请使用 fclose() 函数。函数的原型如下:

 int fclose( FILE *fp );

如果成功关闭文件,fclose( ) 函数返回零,如果关闭文件时发生错误,函数返回 EOF。这个函数实际上,会清空缓冲区中的数据,关闭文件,并释放用于该文件的所有内存。EOF 是一个定义在头文件 stdio.h 中的常量。

 

例子:

FILE *fp = NULL;

fp = fopen("/tmp/test.txt", "w+");

fclose(fp);

 

2.3 读写文本文件

(1) 按照字符读写

下面是从文件读取单个字符函数:

int fgetc( FILE * fp );

函数fgetc()从fp所指向的输入文件中读取一个字符。返回值是读取的字符,如果发生错误则返回EOF

下面是写入单字符的函数:

int fputc( int c, FILE *fp );

函数fputc()把参数c的字符值写入到fp所指向的输出流中。如果写入成功,它会返回写入的字符,如果发生错误,则会返回EOF。

(2) 按照字符串读写

下面是从文件读取字符串函数

char *fgets( char *buf, int n, FILE *fp );

函数 fgets() 从 fp 所指向的输入流中读取 n - 1 个字符。它会把读取的字符串复制到缓冲区,并在最后追加一个 null 字符来终止字符串。

例子:fgets(buff, 255, fp);

下面是从文件写入字符串函数:

int fputs( const char *s, FILE *fp );

举例说明:

fputs("YangLaoShi zui shuai", fp)

 

函数 fputs() 把字符串 s 写入到 fp 所指向的输出流中。如果写入成功,它会返回一个非负值,如果发生错误,则会返回 EOF

(3)格式化存取(重点掌握)

int fscanf(FILE *fp,const char *format)

int fprintf(FILE *fp,const char *format)

它们与printf和scanf函数相仿,都是格式化读写函数,用法也相似。不同之处在于fscanf和fprintf函数是将fp指向的文件作为缓冲区,进行输入输出。

例子:

FILE * fp = fopen("txt_out.txt","w");

例如我们想写入成绩:

fprintf(fp, "%-20.20s %-20.20s %-20.20s %-20.20s %-20.20s %-20.20s %-20.20s\n", "学号", "姓名", "性别", "C语言", "语文", "数学", "英语");

while (i < num)

{

fprintf(fp, "%-20s %-20s %-20s %-20d %-20d %-20d %-20d\n", Pst[i].studentid, Pst[i].name, Pst[i].sex, Pst[i].Cscore, Pst[i].Lscore, Pst[i].Mscore, Pst[i].Escore);

++i;

}

或者获取成绩:

fp = fopen("./student.txt", "r")

fscanf(fp, "%20s %20s %20s %20s %20s %20s %20s", Firstline[0], Firstline[1], Firstline[2], Firstline[3], Firstline[4], Firstline[5], Firstline[6]);

while (fscanf(fp, "%20s %20s %20s %20d %20d %20d %20d", Pst[i].studentid, Pst[i].name, Pst[i].sex, &Pst[i].Cscore, &Pst[i].Lscore, &Pst[i].Mscore, &Pst[i].Escore) != EOF){i++;}

具体细节请自行百度

2.4 读写二进制文件

当要求一次存取一组数据(如,一个数组、一个结构体变量的值),fread和fwrite函数可以解决该类问题。它们的调用形式一般为:

fread(buffer, size, count, fp);
fwrite(buffer, size, count, fp);

buffer:对于fread来说,指的是读入数据的存放地址;对于fwrite来说,是要输出数据的地址。
size:读写数据时,每笔数据的大小
count:读写数据的笔数
fp:文件指针

例子:

fread(pos,sizeof(double),200,fid);

fwrite(pos,sizeof(double),1,fid);//pos为数组名

 

3练习

我们结合所学知识写出部分代码:

//Txt写入
void TxtWrite()
{
	//准备数据
	int index[50] ;
	double x_pos[50], y_pos[50];
	for(int i = 0; i < 50; i ++ )
	{
		index[i] = i;
		x_pos[i] = rand()%1000 * 0.01;
		y_pos[i] = rand()%2000 * 0.01;
	}
	//写入
	FILE * fid = fopen("txt_out.txt","w");
	if(fid == NULL)
	{
		printf("写出文件失败!\n");
		return;
	}
	for(int i = 0; i < 50; i ++ )
		fprintf(fid,"%03d\t%4.6lf\t%4.6lf\n",index[i],x_pos[i],y_pos[i]);
	fclose(fid);
}

//Txt读取
void TxtRead()
{
	FILE * fid = fopen("txt_out.txt","r");
	if(fid == NULL)
	{
		printf("打开%s失败","txt_out.txt");
		return;
	}
	char line[1024];
	memset(line,0,1024);
	while(!feof(fid))
	{
		fgets(line,1024,fid);
		printf("%s\n", line); //输出
	}
	fclose(fid);
}

//二进制文件写入
void DataWrite()
{
	//准备数据
	double pos[200];
	for(int i = 0; i < 200; i ++ )
		pos[i] = i;
	//写入
	FILE *fid;
	fid = fopen("binary.dat","wb");
	if(fid == NULL)
	{
		printf("写出文件出错");
		return;
	}
	fwrite(pos, sizeof(double), 200, fid);
	fclose(fid);
}

//二进制文件读取
void DataRead()
{
	FILE *fid;
double pos[200];
	fid = fopen("binary.dat","rb");
	if(fid == NULL)
	{
		printf("读取文件出错");
		return;
	}
	fread(pos,sizeof(double),200,fid);
	for(int i = 0; i < 200; i++)
		printf("%lf\n", pos[i]);
	fclose(fid);
}

 

 

 

 

收藏 转发 评论