?6.1 将数据写入文件
6.2 文件读写分类函数
6.3 文件定位函数第六章 磁盘数据存储在第五章中我们学习了结构体类型,可以用结构体数组存放学生信息,但这种存储是暂时的,当程序结束运行,这些数据也就消失了,为了长期保存这些数据,我们可以将它们存储到硬盘上,如果需要使用这些数据,
再从硬盘上将它们读出来,这样数据就可以重复使用了第六章我们要学习的主要内容是,
如何将数据写入文件
如何从文件中读取数据
6.1 将数据写入文件
6.1 将数据写入文件例 6-1 将字符 ‘A‘—‘Z‘写入文件保存起来
#include <stdio.h>
#include <stdlib.h>
void main( )
{ char ch; FILE *fp;
fp=fopen("letter.dat","w");
if (fp==NULL)
{ printf("Opening file error! \n");
exit(0); }
for (ch='A'; ch<='Z'; ch++)
fputc(ch,fp);
fclose(fp);
}
// 定义一个文件指针变量
// 打开文件操作
// 判断文件打开是否成功
// 将字符 ch写入到文件中
// 关闭文件
使用文件的必要步骤,
1,定义文件指针变量,文件类型 FILE是在 stdio.h头文件中声明的,可以直接使用
2,打开文件,并判断是否能正确打开文件,如果打开文件失败,则退出程序
3,向文件写入数据,或从文件读取数据,这是最重要的文件操作步骤
4,关闭文件
6.1 将数据写入文件
文件的概念,指存储在外部介质上的数据的集合操作系统是以文件为单位对数据进行管理的。 如果想使用存在磁盘上的数据,必须先按文件名找到指定的文件,然后再从文件中读取数据 ; 如果想在磁盘上存储数据,也必须先建立一个文件,再向它写入数据。
文件除了包括磁盘上存储的内容外,从操作系统的角度看与主机相连的各种输入输出设备也是文件。
例如,键盘是输入文件,显示器是输出文件。
文件的分类
C语言把文件看作是一个字节的序列,即文件是由一个一个字节的数据顺序组成的。根据数据的组织形式把文件分为两类,文本文件和二进制文件。
6.1 将数据写入文件设有一整数 2460,它在内存中的存储形式,0000 1001 1001 1100
2460在文本文件中的存储形式,
0011 0010 0011 0100 0011 0110 0011 0000
2460在二进制文件中的存储形式,0000 1001 1001 1100
二进制文件:数据按其在内存中的存储形式存放在磁盘上优点,节省空间,输入输出速度快缺点,不能直接输出字符形式
6.1 将数据写入文件
文本文件 (ASCII文件 ),每个字节存放一个字符 (即其 ASCII码 )
优点,便于对字符进行处理,可以直接输出字符形式缺点,占用存储空间较多,对于数值型数据,其二进制形式与
ASCII码形式转换需要时间
文件类型指针要使用一个文件需要有一定的信息,如文件当前的读写位置,与文件对应的内存缓冲区地址,文件的操作方式等。
这些信息都存放在“文件信息区”中,“文件信息区”是一个结构体变量,其结构体类型由系统定义,类型名为 FILE?定义形式,FILE * 指针变量名 ;
注意,
1,只有通过文件指针变量才能调用相应的文件
2,有 n个文件就要定义 n个文件指针变量,分别对应各个文件
3,FILE必须大写
6.1 将数据写入文件一,文件的打开
1,fopen函数格式,fopen ( 文件名,文件使用方式 ) ;
fopen函数有返回值,返回值是一个地址,即被打开文件的“文件信息区”的起始地址,使用时应将返回值赋给一个文件指针变量 需要打开的文件名使用文件的方式 (读或写 )让哪个指针变量指向被打开的文件例 FILE *fp ;
fp = fopen ( ―file1‖,―r‖ ) ;
6.1 将数据写入文件
2,打开文件的方法打开文件时,因使用方式不对或其他原因,可能会使打开文件操作失败,这时 fopen函数的返回值是 NULL,
所以在打开文件时通常会判断一下打开操作是否成功例 if ( ( fp =fopen(―file1‖,―r‖) ) = = NULL )
{ printf(―Can not open this file!\n‖) ;
exit( 0 ) ;
}
说明,exit 函数的作用是关闭所有文件,结束程序,
并返回操作系统,也可写成 exit ( ) ;
注意,使用 exit函数要包含头文件 < stdlib.h >
6.1 将数据写入文件
3,文件使用方式
(1),r‖与,rb‖ 只读以此方式打开文件时,该文件必须已经存在,如不存在将出错,
打开文件后只能从文件中读数据,当前读写位置位于文件开头,
(2),w‖与,wb‖ 只写以此方式打开文件时,如有同名文件 (即文件已存在 ),则将原有文件删除并建立一个新文件 ; 如没有同名文件 (即文件不存在 ),则建立一个新文件,打开文件后只能向文件中写数据,当前的读写位置位于文件开头,
(3),a‖与,ab‖ 追加以此方式打开文件时,如有同名文件,则将当前读写位置位于文件末尾,可以追加数据 ; 如无同名文件,则建立一个新文件
(4) 带,+” 号的形式,表示即能读又读写
6.1 将数据写入文件二,文件的关闭
1,fclose函数格式,fclose ( 文件指针变量 ) ;
例,fclose( fp ) ;
作用,将文件指针变量所指向的文件关闭,
即使文件指针变量不再指向该文件,
以后不能通过文件指针变量对该文件进行操作说明,fclose函数的返回值为整型,
若关闭成功返回值为 0,若失败返回值为非零数
6.1 将数据写入文件
2,关闭文件的重要性写文件时,在“输出缓冲区”装满后,才将数据一起写入文件。当程序结束时,缓冲区可能还未满,如未关闭文件就结束程序,则缓冲区数据不能写入文件,会丢失数据。
使用 fclose函数,不论缓冲区是否已满,都会将缓冲区的数据写入文件,再关闭文件。
6.1 将数据写入文件一,输入 /输出单个字符
1,fputc函数 (向文件输出一个字符 )
格式,fputc ( 字符常量或字符变量,文件指针变量 ) ;
作用,将一个字符写到文件指针所指向的文件中去函数返回值,成功时返回该字符,失败时返回 EOF(-1)
说明,写入一个字符后,文件位置指针将自动指向下一个字节
FILE *fp ; char ch ;
if ( ( fp =fopen(―file1‖,―w‖) ) = = NULL )
{ printf(―Can not open this file!\n‖) ; exit( 0 ) ; }
fputc(?s‘,fp ) ;
ch =?t‘ ;
fputc( ch,fp ) ;
将字符常量‘ s‘写入 fp指向的文件 file1
中将字符变量 ch中存放的字符写入 fp指向的文件 file1中
6.2 文件读写分类函数例 6-3 从键盘输入一行字符,写到文本文件 string.txt中
#include <stdio.h>
#include <stdlib.h>
void main( )
{ FILE *fp; char ch;
if( (fp=fopen("string.txt","w") )==NULL)
{ printf("can't open file\n"); exit(0); }
do
{ ch=getchar( ); // 从键盘输入一个字符
fputc(ch,fp); // 将 ch中的字符写到文件中
}while(ch!='\n');
fclose(fp);
}
6.2 文件读写分类函数
2,fgetc函数格式,字符变量 = fgetc( 文件指针变量 ) ;
作用,从文件指针变量所指向的文件中读一个字符,
并将它赋给程序中的一个字符变量函数返回值,成功时返回该字符,失败时返回 EOF
说明,读取一个字符后,文件位置指针将自动指向下一个字节
FILE *fp ; char ch ;
if ( ( fp =fopen(―file1‖,―r‖) ) = = NULL )
{ printf(―Can not open this file!\n‖) ; exit( 0 ) ; }
ch = fgetc ( fp ) ; printf(―%c‖,ch ) ;
注意,EOF 实际是一个符号常量,其值为 –1
一般用 EOF作为文本文件的文件结束符,
用 fgetc函数时,最后读到文件结束时将返回 EOF
6.2 文件读写分类函数例 6-4 将磁盘上一个文本文件的内容复制到另一个文件中
#include<stdio.h>
#include<stdlib.h>
void main( )
{ FILE *fp_in,*fp_out; char ch,infile[20],outfile[20];
printf("Enter the infile name:"); scanf("%s",infile);
printf("Enter the outfile name:"); scanf("%s",outfile);
if((fp_in=fopen(infile,"r"))==NULL)
{ printf("can't open file:%s",infile); exit(0); }
if((fp_out=fopen(outfile,"w"))==NULL)
{ printf("can't open file:%s",outfile); exit(0); }
while( !feof(fp_in) )
{ ch= fgetc(fp_in);
fputc(ch,fp_out);
}
fclose(fp_in); fclose(fp_out);
}
fputc( fgetc(fp_in),fp_out);
while( (ch=fgetc(fp_in))!=EOF )
fputc(ch,fp_out);
二,输入 /输出一个字符串
1,fgets函数格式,fgets( str,n,fp ) ;
说明,str -- 字符数组名,n -- 整数值,fp -- 文件指针变量作用,从 fp指向的文件中读 (n-1)个字符,将它们存放到 str数组中,
并在其后自动加一个‘ \0’,如果读入 (n-1)个字符前遇到换行符或文件结束符 EOF,则结束读入函数返回值,成功返回 str数组的首地址,失败返回 NULL
6.2 文件读写分类函数
2,fputs函数格式,fputs( str,fp ) ;
说明,str -- 字符串常量 或 字符数组名 或 字符指针变量
fp -- 文件指针变量作用,将 str字符串写到 fp所指向的文件中,但‘ \0’不写入文件函数返回值,成功返回 0,出错返回 非 0 值
6.2 文件读写分类函数例 6-5,将文本文件中的内容显示到屏幕上
#include<stdio.h>
#include<stdlib.h>
void main( )
{ FILE *fp; char string[81],filename[20];
printf("Enter the file name:"); gets(filename);
if((fp=fopen(filename,"r"))==NULL)
{ printf("can't open file!\n"); exit(0); }
while( fgets(string,81,fp)!=NULL)
printf("%s",string);
fclose(fp);
}
6.2 文件读写分类函数例 6-6 在文本文件 string.txt末尾添加若干行字符
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
void main( )
{ FILE *fp; char s[81];
if((fp=fopen("string.txt","a"))==NULL)
{ printf("can't open file\n"); exit(0); }
while(strlen(gets(s))>0)
{ fputs(s,fp);
fputs("\n",fp);
}
fclose(fp);
}
例 6-7,从键盘输入一行字符,以‘ #’结束,将这行字符中的小写字母改为大写字母,然后保存到磁盘文件,test‖中
#include <stdio.h>
#include <stdlib.h>
void main( )
{ FILE *fp; char s1[81],s2[81]; int i=0;
if ( ( fp =fopen(―test.txt‖,―w‖) ) = = NULL )
{ printf(―can not open this file!\n‖) ; exit( 0 ) ; }
gets(s1);
while ( s1[i]!=?#‘ )
{ if (s1[i]>=?a‘ && s1[i]<=?z‘ ) s1[i]=s1[i]-32;
fputc(s1[i],fp); i++ ; }
fclose(fp);
fp=fopen( ―test.txt‖,―r‖ );
fgets(s2,i+1,fp );
puts(s1); puts(s2); fclose(fp);
}
三,按“数据块”的方式输入输出
1,格式,fread ( buffer,size,count,fp ) ;
fwrite ( buffer,size,count,fp ) ;
6.2 文件读写分类函数
2,说明
(1) buffer,是一个地址对于 fread,buffer是从文件中读取的数据要存放的存储区的首地址对于 fwrite,buffer是向文件写入数据时存储变量的地址
(2) size,要读写数据所占用的字节数
(3) count,要读写数据项的个数
(4) fp,文件指针变量例 6-8,从键盘输入 10个整数,把它们保存到文件,datafile‖中,
再从文件中读取这些整数,并输出到显示器上方法 1:使用两个整型变量
#include <stdio.h>
#include <stdlib.h>
void main ( )
{ FILE *fp ; int m,n,j ;
if ( ( fp =fopen(―datafile‖,―wb+‖) ) = = NULL )
{ printf(―Can not open this file!\n‖) ; exit( 0 ) ; }
for ( j=0; j<10; j++ )
{ scanf(―%d‖,&m); fwrite(&m,2,1,fp) ; }
rewind ( fp ) ; // 使文件位置指针重新指向文件的开始处
for ( j=0; j<10; j++ )
{ fread (&n,2,1,fp); printf(―%4d‖,n ) ; }
fclose (fp) ;
}
#include<stdio.h>
#include<stdlib.h>
void main ( )
{ FILE *fp ; int a[10],b[10],j ;
if ( ( fp =fopen(―datafile‖,―wb+‖) ) = = NULL )
{ printf(―Can not open this file!\n‖) ; exit( 0 ) ; }
for ( j=0; j<10; j++ ) scanf(―%d‖,&a[j] ) ;
fwrite( a,2,10,fp ) ;
rewind ( fp ) ;
fread ( b,2,10,fp ) ;
for ( j=0; j<10; j++ ) printf(―%4d‖,b[j] ) ;
fclose (fp) ;
}
6.2 文件读写分类函数方法 2:使用数组四,格式化输入输出函数
1,格式:
fprintf (文件指针变量,格式字符串,输出表列 ) ;
fscanf (文件指针变量,格式字符串,输入表列 ) ;
6.2 文件读写分类函数
2,说明:
fprintf和 fscanf函数 的使用方法与 printf和 scanf函数类似,只是多了一个参数 --文件指针变量,该参数用来指出向哪个文件写数据,从哪个文件读数据
int a=5,b=9,c,d;
fprintf(fp,―%d,%d\n‖,a,b); //将 a,b的值写到 fp所指向的文件中
fscanf(fp,―%d %d‖,&c,&d); //从 fp所指向的文件中读 2个整数并将它们分别存放在变量 c,d中
6.2 文件读写分类函数
#include <stdio.h>
#include <stdlib.h>
void main ( )
{ FILE *fp; int a=2,b=5,c=8,d=15;
if ( ( fp=fopen(―exfile.txt‖,―w‖) ) = = NULL )
{ printf(―Can not open this file!\n‖); exit(0); }
fprintf(fp,―%d,%d\n‖,a,b);
fprintf(fp,―%d %d\n‖,c,d);
fprintf(fp,―%d:%d:%d\n‖,10,35,28);
fclose(fp);
}
例 6-9 使用 fprintf函数向文件写入数据例 6-10 使用 fscanf函数从文件读取数据
6.2 文件读写分类函数
#include <stdio.h>
#include <stdlib.h>
void main ( )
{ FILE *fp; int a,b,c,d,x,y,z;
if ( ( fp=fopen(―exfile.txt","r") ) == NULL )
{ printf("Can not open this file!\n"); exit(0); }
fscanf( fp,"%d,%d",&a,&b);
fscanf( fp,"%d %d",&c,&d);
printf("a=%d,b=%d,c=%d,d=%d\n",a,b,c,d);
fscanf( fp,"%d:%d:%d",&x,&y,&z);
printf("x=%d,y=%d,z=%d\n",x,y,z);
fclose(fp);
}
文件的读写位置指针文件中有一个读写位置指针,指向当前读或写的位置。
文件顺序读写,从文件开头依次读写数据直到文件末尾文件位置指针对当前所指向的数据进行读或写操作后,
位置指针会自动指向下一个数据项。
如果能控制位置指针的指向,就能实现随机读写。
文件随机读写:从文件的指定位置读 /写数据
6.3 文件定位函数
1,位置指针复位函数 rewind (无返回值的函数 )
格式,rewind(文件指针变量 ) ;
作用,将文件位置指针重新返回到文件开头
2,文件定位函数 fseek
格式,fseek (文件指针变量,位移量,起始点 );
位移量,是一个 long int 型数据,表示以“起始点”为基点向前或向后要移动的字节数,
正数表示 向前移动 (文件头?文件尾 )
负数表示 向后移动 (文件尾?文件头 )起始点,表示从什么位置为基准移动,用数字代表
0 -- 文件开始处
1 -- 文件位置指针的当前指向
2 -- 文件末尾处函数返回值,成功返回 0,出错返回 非 0 值
6.3 文件定位函数
3,ftell函数格式,长整型变量 = ftell (文件指针变量 );
作用,得到文件中位置指针的当前指向,这个位置是相对于文件开头的位移量函数返回值,成功返回当前位置,出错返回 -1L
例,long n;
n = ftell (fp ) ;
if ( n= = -1L ) printf(―error!‖) ;
6.3 文件定位函数例 6-11,输入学生信息,保存在文件中,再从文件中读取学生信息输出到显示器上#include <stdio.h>
#include <stdlib.h>
#define SIZE 4
struct stud
{ char name[10];
int num;
int score;
} st[SIZE]; // 定义一个全局结构体数组
long len=sizeof(struct stud); // 定义一个全局变量
void save( )
{ FILE *fp; int i ;
if ((fp=fopen(―studata‖,―wb‖))= =NULL)
{ printf(―can not open this file!\n‖); exit(0); }
for( i=0; i<SIZE; i++)
if ( fwrite(&st[i],len,1,fp)!=1 ) printf(―file write error!\n‖);
fclose(fp);
}
void main( )
{ FILE *fp; int i;
struct stud x;
for (i=0; i<SIZE; i++)
scanf(―%s%d%d‖,st[i].name,&st[i].num,&st[i].score);
save( ); // 调用函数将数据保存到文件中
if( ( fp=fopen(―studata‖,―rb‖))==NULL)
{ printf(―can not open this file!\n‖); exit(0); }
for(i=0; i<SIZE; i++)
{ fread(&x,len,1,fp); //从文件读一个结构体数据到 x
printf(―%-10s%4d%4d\n‖,x.name,x.num,x.score);
}
fseek(fp,-2*len,2); // 文件位置指针定位
fread(&x,len,1,fp);
printf(―%-10s%4d%4d\n‖,x.name,x.num,x.score);
fclose(fp);
}