文件操作--文件的随机读写、标准输入输出重定向

目录

一、文件的随机读写

二、便准输入输出重定向


一、文件的随机读写

        前面的例程执行的都是顺序文件处理(Sequential File Processing)。在顺序文件处理过程中,数据项是一个接着一个进行读取或者写入的。例如,如果想读取文件中的第5个数据项,那么使用顺序存取方法必须先读取前4个数据项才能读取第5个数据项。不同于顺序读写的是,文件的随机访问(Random Access)允许在文件中的随机定位,并在文件的任何位置直接读写数据。

        为了实现文件的定位,在每一个打开的文件中,都有一个文件位置指针(File Location Pointer),也称文件位置标记,用来指向当前读写文件的位置,它保存了文件中的位置信息。当对文件进行顺序读写时,每读完一个字节后,该位置指针自动移到下一个字节的位置。当需要随机读写文件数据时,则需要强制移动文件位置指针指向特定的位置。那么如何定位文件的位置指针呢?C语言提供了如下两个函数来定文件位置指针。

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

        void rewind(FILE *fp); 

其中,函数fseek()的功能是将fp的文件位置指针从fromwhere开始移动offset个字节,指示下一个要读取的数据的位置。

        offset是一个偏移量,它告诉文件位置指针要跳过多少个字节。offset为正时,向后移动,为负时,向前移动。ANSI C要求位移量offset是长整型数据(常量数据后要加L)。这样当文件的长度大于64kb是不至于出问题。

        fromwhere用于确定偏移量计算的起始位置,它的可能取值有3中:

1、SEEK_SET或0,代表文件开始处;

2、SEEK_CUR或1,代表文件当前位置;

3、SEEK_END或2,代表文件结尾处。

        通过指定fromwhere和offset的值,可使位置指针移动到文件的任意位置,从而实现文件的随机读取。如果函数fseek()调用成功,则返回0值,否则返回非0值。

        函数rewind()的功能是将文件位置指针指向文件首字节,即重置位置指针到文件首部。

        C语言还提供了一个用来读取当前文件位置指针的函数,其函数原型为:

        long ftell (FILE *fp);

        若函数调用成功,则返回文件的当前读写位置,否则返回-1L。函数ftell()用相对于文件起始位置的字节偏移量来表示返回的当前文件位置指针。

注意:缓冲区为文件传输读写提高了速度,但是也有一些副作用。

例如,在缓冲区内容还未写入磁盘时,计算机突然死机或掉电,数据就会丢失,永远也找不回来。再如,缓冲区被写入无用的数据时,如果不清除,其后的文件读操作都首先会读取那些无用的数据。那么如何解决这个问题呢?

        为了解决这个问题,C语言提供了如下的函数:

        int  fflush (FILE *fp);

fflush()的功能是无条件地把缓冲区中地所有数据写入物理设备。这样,程序员可自己决定再何时清除缓冲区中的数据,以确保输出缓冲区中地内容写入文件。

例题:编程从文件student.txt中随机读取第k条记录地数据并显示到屏幕上,k由用户从键盘输入。

#include <stdio.h>
#include <stdlib.h>
typedef struct date
{
	int year;
	int month;
	int day;
}DATE;
typedef struct student
{
	long studentid;
	char studentname[10];
	char studentsex;
	DATE birthday;
	int score[4];
	float aver;
}STUDENT;
void searchinfile(char filename[],long k);
int main(void)
{
	long k;
	printf("Input the searching record number:");
	scanf("%ld",&k);
	searchinfile("student.txt",k);
	return 0;
 } 

void searchinfile(char filename[],long k)
{
	FILE *fp;
	int j;
	STUDENT stu;
	if((fp = fopen(filename,"r"))==NULL)
	{
		printf("Failure to open %s!\n",filename);
		exit(0);
	}
	fseek(fp,(k-1)*sizeof(STUDENT),SEEK_SET);
	fread(&stu,sizeof(STUDENT),1,fp);
	printf("%10ld%8s%3c%6d/%02d/%02d",stu.studentid,stu.studentname,stu.studentsex,stu.birthday.year,stu.birthday.month,stu.birthday.day);
	for(j=0;j<4;j++)
	{
		printf("%4d",stu.score[j]);
	 } 
	printf("%6.lf\n",stu.aver);
	fclose(fp);
}

 

         程序第28~49行定义的函数searchinfile()的功能是从文件filename中查找并显示第k条记录的数据,函数serchinfile()的第1个形参filename是字符数组,用于存放需要读取的文件名,程序第24行将文件名字符串“student.txt”作为实参传递给形参filename,函数searchinfile()的第2个形参k是长整型变量,表示要读取的记录号,为了在文件中直接读取第k条记录,程序第38行用函数fseek()将文件位置指针从文件开头向后移动(k-1)*sizeof(STUDENT)个字节。

        关于偏移量,这里之所以这样计算偏移量,是因为fseek()的第2个参数要给出文件位置指针所需跳过的字节数,二每条记录的长度是sizeof(STUDENT)个字节。

        同理,因函数ftell()返回的文件位置使用字节偏移量表示的,所以必须通过除以sizeof(STUDENT)才能换算成当前的记录号,例如,若在本例题中:

        printf ("record number = %d\n",ftell(fp)/sizeof(STUDENT)+1);

 

        这说明在执行第38行语句后文件位置指针指向了第2条记录,而用函数fread()读取一条记录数据后,文件位置指针又指向了吓一条记录,即第3条记录。 

二、便准输入输出重定向

        前面程序对数据的输入/输出是通过终端设备来完成的,看似与文件毫无瓜葛,但实际上,对于终端设备,系统自动会打开3个标准文件:标准输入、标准输出和标准错误输出。

相应的,系统定义了3个特别的文件指针常数:stdin、stdout、stderr,分别指向便准输入、输出和错误文件,这3个文件都以标准终端设备作为输入/输出对象。在默认情况下,标准输入设备是键盘,输出设备是屏幕。

1.fprintf是printf的文件操作版,二者的差别就在于fprintf多一个FILE *类型的参数fp。

2.fputc和putchar差别跟fprintf和printf的差别差不多。

例如:

putchar(c);    fputc(c,stdout);

3.getchar();  ==  fgetc(stdin);

4.puts(str);   ==  fputs(str,stdout);

5.fgets()比gets()多一个参数size。

char *fgets(char *s,int size,FILE *stream);

char *gets(char *s);

例如:

gets(buffer);

fgets(buffer, sizeof(buffer),stdin);

        虽然系统隐含的标准I/O文件是指终端设备,但其实标准输入和标准输出是可以重新定向的,操作系统可以重定向它们到其他文件或具有文件属性的设备,只有标准错误输出不能重定向。(简单描述:没有显示器屏幕,重定向后可以通过打印机输出)

这里,用“<”表示输入重定向,用“>”表示输出重定向。

例如:假设exefile是可执行程序的文件名,指向该程序时,需要输入数据,现在如果要求从文件file.in中读取数据,而非键盘输入,那么DOS命令提示符下,只要键入如下命令即可:

C:\exefile.exe<file.in

于是,exefile的便准输入就被重定向到了file.in,此时程序exefile只会专心致志地从文件file.in中读数据,而不再理会你此后按下的任何一个按键。

freopen()可用于指定模式将输入或输出重定向到另一个文件。

常见地使用方式:

freopen("D:\\in.txt","r",stdin);//将输入流定位到in.txt

freopen("CON","r",stdin); //将输入流还原到键盘

freopen("D:\\out.txt","w",stdout);//将输出流定位到out.txt

freopen("CON","w",stdout);//将输出流还原到屏幕 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++ 文件读写可以使用标准库中的文件流(fstream)类来实现。fstream 类可以读写文件,可以像读写流一样使用运算符进行输入输出操作。 下面是一个简单的例子,演示了如何打开一个文本文件、写入数据、读取数据和关闭文件: ```c++ #include <iostream> #include <fstream> using namespace std; int main() { string filename = "example.txt"; ofstream outfile(filename); // 打开文件 if (outfile.is_open()) { outfile << "Hello World!" << endl; // 写入数据 outfile.close(); // 关闭文件 } else { cout << "Unable to open file" << endl; return 1; } ifstream infile(filename); // 打开文件 if (infile.is_open()) { string line; while (getline(infile, line)) { // 读取数据 cout << line << endl; } infile.close(); // 关闭文件 } else { cout << "Unable to open file" << endl; return 1; } return 0; } ``` 在这个例子中,我们首先创建了一个 `ofstream` 对象,使用 `filename` 参数打开了一个文件。然后我们使用运算符 `<<` 将字符串“Hello World!”写入文件中,最后关闭了文件。 接着,我们打开了同样的文件,这次使用了 `ifstream` 对象。我们使用 `getline` 函数来读取每一行的数据,并使用 `cout` 输出到控制台上。 最后我们关闭了文件,退出程序。 需要注意的是,如果文件不存在,fstream 类会自动创建一个新的文件。如果文件已经存在,则会清空原有内容,并写入新的数据。如果要追加数据到文件末尾,可以使用 `ofstream::app` 或 `fstream::app` 模式打开文件,例如: ```c++ ofstream outfile(filename, ios::app); ``` 同时还有其他的文件打开模式,可以通过设置第二个参数来实现。常见的模式包括: - `ios::in` :以只读模式打开文件。 - `ios::out` :以写入模式打开文件。 - `ios::binary` :以二进制模式打开文件。 - `ios::ate` :打开文件并将文件指针移动到文件末尾。 - `ios::trunc` :如果文件已经存在,则清空文件内容。 以上是 C++ 文件读写的基本操作,您可以根据实际需求进行更加复杂的文件操作

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值