知识点13:文件

1,文件的打开与关闭

fopen函数:fp = fopen(文件名, 使用文件方式);若打开文件失败,会返回NULL(即0)。

	FILE *fp;
	if((fp = fopen("F:\\test.txt", "w")) == NULL)//文件名的输入必须用双斜杠,以与转义字符区分。如果文件与该c文件在同一个文件内,则可以直接写出文件名即可;若不在一起,则要完整地输入文件标识(含途径)
	//或者也可以:if( !(fp = fopen("F:\\test.txt", "w")) )
	{
    
    
		printf("error!");
		exit(0); //exit在stdlib头文件内,作用:关闭所有文件,终止正在执行的程序
	}//设置一个文件打开失败检测步骤
	理论上每一条关于文件的操作之后都应该判断是否成功 
	else printf("open successfully!");
	fclose(fp);
	FILE *fp;
	char ch, filename[20];
	printf("请输入文件名:");
	scanf("%s", filename);
	ch = getchar();//用scanf输入字符串时,回车表示输入的字符串到此结束,但“回车”符仍保留在缓冲区中,因此需要加一个getchar()来将其读取,即“消化”掉,从而避免之后会将其作为有效字符读取。
	if ( !(fp = fopen(filename, "r+")) )//数组名即一个指针! 
	{
    
    
		printf("can not open the file!\n");
		exit(0);
	}

为防止因为关闭源文件而造成的数据流失,在程序结束之前应关闭所有文件。
fclose函数fclose(文件指针);关闭成功会返回0;否则返回EOF。

2,文件的读写

注意文件的读写方式

1,读写单个字符

fputc函数:
将一个字符(字符常量、字符变量均可)写到磁盘文件中。fputc(ch, fp);输出成功则返回所输的字符;输出失败则返回EOF。

	ch = getchar();//从缓冲区接收键盘输入的第一个字符
	/*调用getchar()函数时,输入的字符被存放到缓冲区中,直到按回车为止(回车符也放到缓冲区中),
	之后getchar()函数才开始从缓冲区中每次一个地读入字符和其它操作,直到缓冲区的字符读完后才重新等待用户输入*/ 
	while (ch != EOF)
	{
    
    
		fputc(ch, fp);//回车也会输出
		ch = getchar();//直接从缓冲区读取
	}

fgetc函数:
从磁盘文件中读取一个字符。ch = fgetc(fp);读取到文件结束符时返回EOF。
c即character,只输入一个 字符(单引号) 给文件

2,读写字符串

fgets函数:
从文件读取字符串并存入字符数组中。char *fgets(char *str, int n, FILE *stream) 其中n是每次最多读取的字符个数,实则最多只读取n-1个字符,最后一个字符为‘\0’,作为字符串结束标志。
当读取 (n-1) 个字符时,或者读取到换行符时(换行符也被读取到,并存入数组中),或者到达文件末尾时,本次读取结束。如果到达文件末尾或者没有读取到任何字符,返回NULL。
同一个数组,第二次调用fgets函数时,数组中的数据会全部消失,重新从str[0]开始存储。

	//可以通过 一次一次的 读取,最终读取所有内容 
	while (fgets(str, n, fp) != NULL)
	{
    
    
		printf("%s", str);
	} 

fputs函数:
将字符数组中的字符串输入到文件中:int fputs(const char *str, FILE *stream)输入的字符中不包括字符串的结束符’\0’,因此为防止输入的字符串连在一起,需要进行人为的分开fputs("\n",fp);。输入成功则返回一个非负值,否则返回EOF。
fputs() 和 puts() 有两个小区别:
1,puts() 只能向标准输出流输出(即屏幕输出),而 fputs() 可以向任何流输出。
2,使用 puts() 时,系统会在自动在其后添加换行符;而使用 fputs() 时,系统不会自动添加换行符,因此有时需手动输入一个换行符。fputs("\n", fp);

3,格式化输入输出

fprintf函数:
将数据以指定的格式输入到文件中:int fprintf(FILE *stream, const char *format, ...)如果成功,则返回写入的字符总数,否则返回一个负数。
fscanf函数:
从文件中读取数据,赋给程序中的变量:int fscanf(FILE *stream, const char *format, ...)如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回 EOF。

	FILE *fp;
	if( ( fp = fopen("F:\\test.txt", "a") ) == NULL )//注意文件的访问方式 
	{
    
    //比如这里应用a追加的方式,因为之后还需要读取文件中的数据,如果用w则是将文件全部清空,再重新从文件起始处输入,会使之后读取的数就是刚刚输入的数 
		printf("error!");
		exit(0);	
	}
	int i = 200, j;
	fprintf(fp, "%d", i);//将i输出到fp所指的文件中 
	fclose(fp);
	fp = fopen("F:\\test.txt", "r");//关闭并重新打开文件,使指针回到文件初的位置 
	fscanf(fp, "%d", &j);//从fp所指的文件中读取数,赋给j 
	printf("%d", j);
	fclose(fp);

4,读写整块数据

fread函数:
从fp所指向的文件中读取count次,每次读size字节,读入的信息存储在buffer地址中。fread(buffer, size, count, fp)函数执行成功会返回count的值。
fwrite函数:
将从buffer地址开始的信息输出count次,每次写size字节到fp所指的文件中。fwrite(buffer, size, count, fp)函数执行成功会返回count的值
fread、fwrite函数用于二进制文件的输入输出,因为它们是按数据块的长度来处理输入输出的,不出现字符转换。

   FILE *fp;
   char c[] = "This is runoob";
   char buffer[20];
   fp = fopen("file.txt", "w+");
   
   /* 写入数据到文件 */
   fwrite(c, strlen(c) + 1, 1, fp);//一个字符占一个字节

   fseek(fp, 0, SEEK_SET);//将文件指针移到文件开头
 
   /* 读取并显示数据 */
   fread(buffer, strlen(c)+1, 1, fp);
   printf("%s\n", buffer);
   fclose(fp);

fread与fwrite函数常用于处理数组、结构体类型,结合sizeof函数

struct Student
{
    
    
	char name[10];
	int num;
	int math;
}score[100];

for (i = 0; i < n; i ++)
	if (fwrite(&score[i], sizeof(struct Student), 1, fp) != 1)//函数执行成功会返回count的值(此处为1)
		printf("error");

fread(&score[i], sizeof(struct Student), 1, fp);

3,文件的定位

1,最基本的情况:用关闭文件再打开文件使文件位置指针回到文件开头。

2,运用rewind函数使文件位置指针回到文件开头。rewind(fp);该函数没有返回值。

3,文件所有内容的最后会紧跟一个文件尾标志EOF。
feof函数可用来检测文件尾标志是否已被读取过。未读取到EOF(即文件未读取结束)时,feof函数的值为0;文件读取结束时,feof的值为1。
常见用法:while( !feof(fp) )

4,用ftell函数得出文件位置指针的当前位置。ftell函数的值为与文件开头的距离(相对位移量)。

	fp=fopen("F:\\test\\a.txt","r");
	
	printf("%d ",ftell(fp));//开始时,"文件读写位置标记"位于第一个字节,又ftell输出的是相对于文件开头的位移量来表示 
	                        //因此此时ftell的值为0                                      相对位置!!! 
	while(!feof(fp))
	{
    
    
		putchar(fgetc(fp));//fgetc函数直接作参数
		printf("%d ",ftell(fp));//每访问完一个字节后,读写位置自动后移一个字节,即ftell的返回值自动+1 
	}                           //此时位置读写标记指向的是一个还没有被访问的字节 

在访问完最后一个字符后,文件位置标记就指向了最后一个字符的后面。这指向没什么, 可是当读取该字节时,会读取到-1,即EOF文件结束,文件指针不会再往后移,putchar(-1)时会输出一个长空格。注意:不要以为最后有一个字节里存放了数值-1,这只是一种处理方法
读取到EOF时,feof函数的值改变。

5,借助fseek函数可以移动位置指针,从而实现随机读写。一般格式为fseek(文件指针, 位移量, 起始点);

起始点 符号表示 数字表示
文件首 SEEK_SET 0
当前位置 SEEK_CUR 1
文件尾(EOF处) SEEK_END 2

“位移量”表示移动的字节数,要求为long型数据,以便在文件长度大于64KB时不会出错。因此当用常量来表示位移量时,要加后缀L,以转为long型。
例如fseek(fp, -20L, 1);//表示将位置指针从当前位置向开头方向移动20个字节。
fseek函数通常用于二进制文件。文本文件由于要进行转换,故往往计算的位置会出现错误。

4,出错检测

1,ferror函数:int ferror(FILE *stream)
检测给定流里的文件错误。没有错误则返回0;有错则返回非零值。
执行fopen函数时,ferror函数的初始值自动置为0(无论文件是否成功打开)。如果在上一个文件操作中该文件中引入了一些错误,则通过ferror()函数,我们可以确定在上一个操作期间该文件中存在一些错误。

   if( ferror(fp) )
      printf("error");
   clearerr(fp);//注意clearerr函数的写法,末尾有两个r

调用ferror函数后应立即调用clearerr函数,以将ferror函数的值再次变为0,从而可以进行下一次的检测 ;否则,ferror函数的值会一直保留,直到调用clearerr或rewind函数或任何其它一个输入输出函数

猜你喜欢

转载自blog.csdn.net/Shao_yihao/article/details/113432775