C语言文件操作

实验目的
学习C语言中对文件的操作,熟悉指针
掌握基本查找,排序,删除,调换,改变,添加算法
实验要求
了解课程内容,熟悉文件操作,并能够自己写出函数对文件进行操作
实验内容
一、 几个概念理解:
文件:按一定规则存储在磁盘上的数据集合。
文件名:能唯一标识某个磁盘文件的字符串。形式:盘符:/路径/文件名.扩展名
文本文件:数据以其数字字符的ASCII码形式、一个字节一个字节地存储在磁盘上。
二进制文件:数据以二进制形式在存储在磁盘上。
设备文件:输入/输出设备
标准输入:键盘
标准输出/标准错误输出:显示器
文件型指针:C语言是通过名为FILE的结构型指针来管理文件读写的。FILE *<变量名>
文件的打开和关闭:文件操作先建立文件与文件指针之间的关系,接着进行文件的读与写。建立文件与文件指针之间的联系的过程是文件的打开,终止这种联系就是文件的关闭。

FILE结构:定义在〈stdio.h〉中。形式如下:
typedef struct
{
int _fd;   /*文件代号*/
int _cleft;       /* 文件缓冲区所剩字节数*/
int _mode;     /* 文件使用模式*/
char * nextc;     /* 下一个等待处理的字节地址, 即文件内部指针*/
char * buff;     /*  文件缓冲区首地址  */
}FILE;

二、 主要操作函数
1 文件的打开与关闭:
1.1 打开文件函数fopen()
功能:打开文件
用法:fopen(char* filename,  char* mode);
一般形式:文件指针名=fopen(文件名,使用文件方式);
返回值:文件指针
#include <stdio.h>
FILE *fp;
fp = fopen(char* filename,  char* made);
if(fp == NULL) /*一般在打开文件后判断文件指针为否为空*/
{
exit(0);
}
fclose(fp);
mode种类有:
r:打开只读文件,该文件必须存在。
r+:打开可读写的文件,该文件必须存在。
w :打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件。
w+:打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。
a:以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。
a+:以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。
全部十二种打开方式如有兴趣参考附录一

1.2 关闭文件函数fclose()
功能:关闭文件指针
返回值:0表示关闭顺利,非0关闭时出错
在使用完一个文件后应该关闭它,以防止它再被误用。"关闭"就是使文件指针变量不指向该文件,此后不能再通过该指针对其相连的文件进行读写操作,除非再次打开,使该指针变量重新指向该文件。
用fclose函数关闭文件。fclose函数调用的一般形式为: fclose(文件指针);
例如:fclose(fp); 用fclose函数打开文件时所带回的指针赋给了fp,现把该文件关闭。应养成在程序终止上前关闭所有使用的文件的习惯,如果不关闭文件将会丢失数据。fclose函数返回一个值,顺利执行关闭操作返回值为0;如果返回非0值,则表示关闭时有错误。
2 文件的读与写:
对文件的读和写是最常用的文件操作。在C语言中提供了多种文件读写的函数:
使用以上函数都要求包含头文件stdio.h
字符读写函数 :fgetc和fputc
字符串读写函数:fgets和fputs
数据块读写函数:fread和fwrite //这两个函数感兴趣的同学可以深入
格式化读写函数:fscanf和fprinf
1.1 字符读写函数 :fgetc和fputc
函数名:fgetc()
函数说明:fgetc( )函数从输入流的当前位置返回一个字符,并将文件指针指示器移到下一个字符处,如果已到文件尾,函数返回EOF,此时表示本次操作结束,若读写文件完成,则应关闭文件。
函数用法:char fgetc(FILE *stream)
返回值:成功:返回值所得到的字符;失败:返回EOF(-1)。

对于fgetc函数的使用有以下几点说明:
1. 在fgetc函数调用中,读取的文件必须是以读或读写方式打开的。
2. 读取字符的结果也可以不向字符变量赋值
例如:
fgetc(fp);
但是读出的字符不能保存
3. 在文件内部有一个位置指针。用来指向文件的当前读写字节。在文件打开时,该指针总是指向文件的第一个字节。使用fgetc 函数后,该位置指针将向后移动一个字节。 因此可连续多次使用fgetc函数,读取多个字符。应注意文件指针和文件内部的位置指针不是一回事。文件指针是指向整个文件的,须在程序中定义说明,只要不重新赋值,文件指针的值是不变的。文件内部的位置指针用以指示文件内部的当前读写位置,每读写一次,该指针均向后移动,它不需在程序中定义说明,而是由系统自动设置的。
分析工程fgetc

函数名:fputc()
函数说明:fputc()函数完成将字符ch的值写入所指定的流文件的当前位置处,并将文件指针后移一位。fputc()函数的返回值是所写入字符的值,出错时返回EOF。
函数用法:char fputc(char ch,FILE *stream)
返回值:成功:返回值所得到的字符;失败:返回EOF(-1)。

对于putc函数的使用也要说明几点:
1. 被写入的文件可以用写w、读写rw、追加方式打开,
2. 每写入一个字符,文件内部位置指针向后移动一个字节。
3. fputc函数有一个返回值,如写入成功则返回写入的字符,否则返回一个EOF。可用此来判断写符,写入一个文件,再把该文件内容读出显示在屏幕上。
分析工程fputc
1.2 字符串读写函数:fgets和fputs
char *fgets(char *str,int num,FILE *stream)
fgets() 函数从文件流stream中读取至多num-1个字符,并把它们放入str指向的字符数组中,在读入的最后一个字符后加上串结束标志'\0'。读取字符直到遇见回车符或EOF(文件结束符)为止,或读入了所限定的字符数。
int fputs(char *str,FILE *stream)
fputs( )函数将str指向的字符串写入流文件。操作成功时,函数返回0值,失败返回非零值。
参考程序fgets_and_fputs工程
1.3 数据块读写函数:fread和fwrite (参考,有兴趣同学见附录三)
int fwrite(char * buf, unsigned size, unsigned n, FILE *fp); size 每个数据的字节数,n个数据. 成功返回写入字符的个数。
int fread(char *buf, unsigned size, unsigned n, FILE *fp);   成功返回读取字符的个数。把指定格式的数据写入文件, 或读取指定格式的数据
例如:fread(fa,4,5,fp); 其意义是从fp所指的文件中,每次读4个字节(一个实数)送入实数组fa中,连续读5次,即读5个实数到fa中。
1.4 格式化读写函数:fscanf和fprinf

函数名: fscanf()
功能: 从一个流中执行格式化输入
用法: int fscanf(FILE *stream, char *format[,argument...]);
函数说明:fscanf()会自参数stream的文件流中读取字符串, 再根据参数format 字符串来转换并格式化数据。转换后的结构存于对应的参数内。
返回值:成功则返回参数数目, 失败则返回-1

函数名:fprintf()
功能: 传送格式化输出到一个文件中
用法: int fprintf(FILE *stream, char *format[, argument,...]);
返回值:成功时返回转换的字节数,失败时返回一个负数

分析程序ReadFile

3 文件位置的确定与指针管理.
1.5 int  feof(FILE *fp);
文件尾的测试: int feof(FILE *fp); //当前已到达文件尾返回非0, 否则返回0
1.6 int  rewind(FILE *fp);
把文件内部指针重新定位到文件的起始位置
1.7 int  fseek(FILE *fp, long offset, int from);
把文件内部指针定位到指定的位置:     //成功返回0
from 是定位的起始点.
SEEK_SET    0    从文件头开始
SEEK_CUR    1    从文件内部指针当前位置开始
SEEK_END    2   从文件尾开始
offset是以From为起始点的依稀字节数,大于0表示向文件尾方向, 0不移动,
1.8 int  ferror(FILE *fp);
文件操作出错测式
用于对由FP指向的文件最近一次操作进行正确性测试. 出错返回非0,还没返回0
文件的删除
删除文件,原型是int remove(const char *filename); 参数就是要删除的文件名,成功返回0。

更多函数附录二
三、 经验总结.
char ch;
ch = getchar()功能等价于ch = fgetc(stdin)功能等价于scanf("%c",ch)功能等价于fscanf(stdin, "%c",ch)
putchar(ch)功能等价于printf("%c",ch)功能等价于fputc(stdout)功能等价于fprintf(stdout, "%c", ch)
注意:这些函数存在的一些细微的差别。注意它们的返回值的不同。

附录:
附录一:全部文件打开方式
使用文件的方式共有12种,下面给出了它们的符号和意义。
文件使用方式 意义
1. rt只读打开一个文本文件,只允许读数据
2. wt只写打开或建立一个文本文件,只允许写数据
3. at追加打开一个文本文件,并在文件末尾写数据
4. rb只读打开一个二进制文件,只允许读数据
5. wb只写打开或建立一个二进制文件,只允许写数据
6. ab 追加打开一个二进制文件,并在文件末尾写数据
7. rt+ 读写打开一个文本文件,允许读和写
8. wt+ 读写打开或建立一个文本文件,允许读写
9. at+ 读写打开一个文本文件,允许读,或在文件末追加数据
10. rb+ 读写打开一个二进制文件,允许读和写
11. wb+ 读写打开或建立一个二进制文件,允许读和写
12. ab+ 读写打开一个二进制文件,允许读,或在文件末追加数据

1) 文件使用方式由r,w,a,t,b,+六个字符拼成,各字符的含义是:
r(read): 读
w(write): 写
a(append): 追加
t(text): 文本文件,可省略不写
b(banary): 二进制文件
+: 读和写
2) 凡用“r”打开一个文件时,该文件必须已经存在,且只能从该文件读出。
3) 用“w”打开的文件只能向该文件写入。若打开的文件不存在,则以指定的文件名建立该文件,若打开的文件已经存在,则将该文件删去,重建一个新文件。
4) 若要向一个已存在的文件追加新的信息,只能用“a”方式打开文件。但此时该文件必须是存在的,否则将会出错。

附录二:更多函数
更多文件相关函数详解
Rewind()函数:将文件指针重新指向一个流的开头
原型:int rewind(FILE *stream);
其实本函数相当于fseek(fp,0L,SEEK_SET);
例子:一般我们会通过下面的方法来获取文件中字符的个数:
    FILE *fs=fopen("C:\1.txt","r");//创建文件流
    long length=0;//声明文件长度
    fseek(fs,0,SEEK_END);//将文件内部指针放到文件最后面
    length=ftell(fs);//读取文件指针的位置,得到文件字符的个数
    rewind(fs);//将文件指针重置到文件最前面

fseek()函数:把fp的文件读写位置指针移到指定的位置。
int fseek(FILE *fp,long offset,int origin);
origin指的是“起始点”,它有三个常量的值,如下:
起始点对应的数字   代表的文件位置
SEEK_SET 0   文件开头
SEEK_CUR 1   文件当前位置
SEEK_END 2   文件末尾

Ftell()函数:得到流式文件的当前读写位置,其返回值是当前读写位置偏离文件头部的字节数。
原型:long ftell(FILE *fp)

feof()
检测是否已到文件尾,是返回真,否则返回0,其原型是int feof(FILE *stream);

附录三
见参考程序fread_and_fwrite工程
fread(pBuffer,size,count,pFile);
fwrite(pBuffer,size,count,pFile);
要读写一个数据块的话,无论是读还是写,都需要指定一个起始地址,读的话从这个起始地址读,写的话从这个起始地址写,上面函数定义中的第一个参数pBuffer就是用于指定这个起始地址,size读写的字节数,count则指定读写多少个size大小的数据,pFile是文件结构指针。
具体程序参考源程序,以下代码片段
写文件
for(i=0;i<2;i++)
{
scanf("%s %s %f %f",student.name,student.num,&student.score[0], &student.score[1]);
/* 输入一记录*/
fwrite(&student,sizeof(student),1,fp1); /*成块写入文件*/
}
读文件
for (i=0;i<2;i++)
{
fread(&student,sizeof(student),1,fp1); /* 从文件成块读*/
printf("%s %s %7.2f %7.2f\n",student.name, student.num,
student.score[0], student.score[1]); /* 显示到屏幕*/
}

Related Articles

Quote Of The Day