文件
文件的基本概念
所谓“文件”是指一组相关数据的有序集合。 这个数据集有一个名称,叫做文件名。 实际上在前面的各章中我们已经多次使用了文件,例如源程序文件、目标文件、可执行文件、库文件 (头文件)等。文件通常是驻留在外部介质(如磁盘等)上的, 在使用时才调入内存中来。从不同的角度可对文件作不同的分类。从用户的角度看,文件可分为普通文件和设备文件两种。
普通文件是指驻留在磁盘或其它外部介质上的一个有序数据集,可以是源文件、目标文件、可执行程序; 也可以是一组待输入处理的原始数据,或者是一组输出的结果。对于源文件、目标文件、可执行程序可以称作程序文件,对输入输出数据可称作数据文件。
设备文件是指与主机相联的各种外部设备,如显示器、打印机、键盘等。在操作系统中,把外部设备也看作是一个文件来进行管理,把它们的输入、输出等同于对磁盘文件的读和写。通常把显示器定义为标准输出文件, 一般情况下在屏幕上显示有关信息就是向标准输出文件输出。如前面经常使用的printf,putchar 函数就是这类输出。键盘通常被指定标准的输入文件, 从键盘上输入就意味着从标准输入文件上输入数据。scanf,getchar函数就属于这类输入。
从文件编码的方式来看,文件可分为ASCII码文件和二进制码文件两种。
ASCII文件也称为文本文件,这种文件在磁盘中存放时每个字符对应一个字节,用于存放对应的ASCII码。例如,数5678的存储形式为:
ASC码: 00110101 00110110 00110111 00111000
↓ ↓ ↓ ↓
十进制码: 5 6 7 8 共占用4个字节。ASCII码文件可在屏幕上按字符显示, 例如源程序文件就是ASCII文件,用DOS命令TYPE可显示文件的内容。 由于是按字符显示,因此能读懂文件内容。
二进制文件是按二进制的编码方式来存放文件的。 例如, 数5678的存储形式为: 00010110 00101110只占二个字节。二进制文件虽然也可在屏幕上显示, 但其内容无法读懂。C系统在处理这些文件时,并不区分类型,都看成是字符流,按字节进行处理。 输入输出字符流的开始和结束只由程序控制而不受物理符号(如回车符)的控制。 因此也把这种文件称作“流式文件”。
本章讨论流式文件的打开、关闭、读、写、 定位等各种操作。文件指针在C语言中用一个指针变量指向一个文件, 这个指针称为文件指针。通过文件指针就可对它所指的文件进行各种操作。定义说明文件指针的一般形式为: FILE* 指针变量标识符; 其中FILE应为大写,它实际上是由系统定义的一个结构,该结构中含有文件名、文件状态和文件当前位置等信息。 在编写源程序时不必关心FILE结构的细节。例如:FILE *fp; 表示fp是指向FILE结构的指针变量,通过fp 即可找存放某个文件信息的结构变量,然后按结构变量提供的信息找到该文件, 实施对文件的操作。习惯上也笼统地把fp称为指向一个文件的指针。文件的打开与关闭文件在进行读写操作之前要先打开,使用完毕要关闭。 所谓打开文件,实际上是建立文件的各种有关信息,并使文件指针指向该文件,以便进行其它操作。关闭文件则断开指针与文件之间的联系,也就禁止再对该文件进行操作。
写在前面:最近终于做了我最讨厌的文件读写操作,从java那时我就不是很喜欢做这个部分,现在勉强比那时好些,今天研究了一些c对文件的操作(这里只是读写)一些问题,感觉状态还不错,找了几篇文章,我把个人认为比较不错的部分做了整理。
/*
一个简单的使用FILE结构体进行字符串处理的例子
我们需要同时处理三个文件。文件add.txt记录了某些人的姓名和地址;文件tel.txt记录了顺序不同的上述人的姓名与电话号码。希望通过对比两个文件,将同一人的姓名、地址和电话号码记录到第三个文件all.txt
<main.c>
*/
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
int main()
{
int len;
FILE *fpAddr,*fpTel,*fpAll;/*定义文件指针*/
char temp[15],nameStr[15],addAndTelStr[15];
if((fpAddr=fopen("addr.txt","r"))==NULL)/*打开文件*/
{
printf("can not open file");
exit(0);
}
if((fpTel=fopen("tel.txt","r"))==NULL)
{
printf("can not open file");
exit(0);
}
if((fpAll=fopen("all.txt","w"))==NULL)
{
printf("can not open file");
exit(0);
}
while(strlen(fgets(nameStr,15,fpAddr))>1)//读回的姓名字段长度大于1*
{
fgets(addAndTelStr,15,fpAddr);/*读地址*/
fputs(nameStr,fpAll);/*写入姓名到合并文件*/
fputs(addAndTelStr,fpAll);/*写入地址到合并文件*/
strcpy(temp,nameStr);/*保存姓名字段*/
//查找姓名相同的记录
do
{
fgets(nameStr,15,fpTel);
fgets(addAndTelStr,15,fpTel);
}while(strcmp(temp,nameStr)!=0);
//rewind(fpTel);/*将文件指针移到文件头,以备下次查找*/
fseek(fpTel,0,SEEK_SET);
fputs(addAndTelStr,fpAll);/*将电话号码写入合并文件*/
}
fclose(fpAddr);/*关闭文件*/
fclose(fpTel);
fclose(fpAll);
return 0;
}