C流式文件操作

关键字:

普通文件、设备文件;

文件文件、二进制文件;

流式文件

FILE *

字符读写、串读写、块读写、格式化读写。

换行符,EOF,串结束符

随机读写

 


 

文件的基本概念

  所谓"文件"是指一组相关数据的有序集合。文件通常是驻留在外部介质(如磁盘等)上的, 在使用时才调入内存中来。从不同的角度可对文件作不同的分类。

 

从用户的角度看,分为普通文件和设备文件:

  普通文件 是指驻留在磁盘或其它外部介质上的一个有序数据集。可以是源文件、目标文件、可执行程序(可以称作程序文件);也可以是一组待输入处理的原始数据,或者是一组输出的结果(可称作数据文件)。

  设备文件 是指与主机相联的各种外部设备,如显示器、打印机、键盘等。在操作系统中,把外部设备也看作是一个文件来进行管理,把它们的输入、输出等同于对磁盘文件的读和写。 通常把显示器定义为标准输出文件,相关函数有printf,putchar等。键盘通常被指定标准的输入文件,相关函数有scanf,getchar等。

 

从文件编码的方式来看,分为ASCII码文件和二进制码文件:

  ASCII文件也称为文本文件,这种文件在磁盘中存放时每个字符对应一个字节,用于存放对应的ASCII码。

例如,数5678的存储形式为:

BYTE:  00110101 00110110 00110111 00111000

     ↓↓

ASCII:  '5''6'    '7''8'

共占用4个字节。ASCII码文件可在屏幕上按字符显示,例如源程序文件就是ASCII文件,用DOS命令TYPE查看文件的内容。

  二进制文件是按二进制的编码方式来存放文件的。 

例如,数5678的存储形式为: 

00010110 00101110

只占二个字节。

 

C系统在处理这些文件时,并不区分类型,都看成是字符流,按字节进行处理。输入输出字符流的开始和结束只由程序控制而不受物理符号(如回车符)的控制。 因此也把这种文件称作"流式文件"。 // C语言中还有 IO型文件

 


 

本节学习流式文件的打开、关闭、读、写、 定位等各种操作。

在讲这些函数之间,先了解一个概念 FILE

 

文件指针

在C语言中用一个指针变量指向一个文件,通过文件指针可对文件进行各种操作。 

 

FILE* 指针变量标识符; 

其中

FILE,是由系统定义的一个结构, 该结构中含有文件名、文件状态和文件当前位置等信息。 各种文件操作函数已经封装了对它的操作,用户编程操作文件时不必关心FILE结构的细节。

例如:

FILE *fp; 表示fp是指向FILE结构的指针变量,通过fp 即可找存放某个文件信息的结构变量,然后按结构变量提供的信息找到该文件, 实施对文件的操作。FILE结构关联一个文件,打开文件时建立此关联,关闭文件时断开关联。习惯上把fp称为指向一个文件的指针。

 

流式文件 打开和关闭函数

文件的打开与关闭文件在进行读写操作之前要先打开,使用完毕要关闭。 所谓打开文件,实际上是建立文件的各种有关信息, 并使文件指针指向该文件,以便进行其它操作。关闭文件则断开指针与文件之间的联系,也就禁止再对该文件进行操作。

文件打开函数 fopen

文件指针名=fopen(文件名,使用文件方式

其中

"文件指针名是被说明为FILE 类型的指针变量。

"文件名是被打开文件的文件名, 是字符串常量或字符数组。

"使用文件方式"是指文件的类型和操作要求。

 

例如:

在当前目录下打开文件file a, 只允许进行""操作。

FILE *fp

fp=("fileA","r");

 

例如:

打开C驱动器磁盘的根目录下的文件hzk16, 这是一个二进制文件,只允许按二进制方式进行读操作。

FILE *fphzk

fphzk=("c:\\hzk16","rb")

 

使用文件的方式共有12

方式

意 义

"rt"

只读打开 文本文件

"wt"

只写打开或建立 文本文件

"at"

追加打开 文本文件

"rb"

只读打开 二进制文件

"wb"

只写打开或建立 二进制文件

"ab"

追加打开 二进制文件

"rt+"

读写打开 文本文件

"wt+"

读写打开或建立 文本文件

"at+"

读写打开文本文件,可追加

"rb+"

读写打开二进制文件

"wb+"

读写打开或建立二进制文件

"ab+"

读写打开二进制文件,可追加

 

说明:

1. 文件使用方式由r,w,a,t,b+六个字符拼成,各字符的含义是:

r(read)   

w(write)  

a(append) 追加

+        读和写

t(text)    文本文件,可省略不写

b(banary) 二进制文件

 

2. 用"r"打开的文件只能读,且文件必须已经存在。

 

3. 用"w"打开的文件只能写。 若文件不存在,建立之,否则,覆盖之。

 

4. "a"打开的文件只能写,内容追加。文件必须已经存在,否则出错。

 

5. 打开文件出错时,fopen将返回 NULL

 

6. 对于文本文件,读入内存时转换为二进制形式,写入硬盘时转换为文本形式,转换需要一点点时间。对二进制文件的读写不存在这种转换。

 

7. 文件使用完毕,应关闭之,以避免数据丢失等错误。

 

8. 标准输入文件(键盘),标准输出文件(显示器 ),标准出错输出(出错信息)由系统打开,可直接使用。

 

文件关闭函数fclose

fclose(文件指针); 

正常关闭时返回0,否则返回非零。

 

流式文件的读写

C提供多种文件读写的函数:

·字符读写函数 :fgetcfputc

·字符串读写函数:fgetsfputs

·数据块读写函数:freedfwrite

·格式化读写函数:fscanffprinf

文件操作函数说明在头文件stdio.h

 

字符读写函数 fgetc, fputc

一、读字符函数fgetc

  字符变量=fgetc(文件指针); 

例如:

ch=fgetc(fp); 

 

说明:

可连续多次使用fgetc函数,读取多个字符。在文件内部有一个位置指针,指向文件的当前读写字节。在文件打开时,该指针总是指向文件的第一个字节。使用fgetc函数后,该位置指针将向后移动一个字节。 

应区别 文件指针和文件内部的位置指针不是一回事。

文件指针 是指向整个文件的,须在程序中定义说明,只要不重新赋值,文件指针的值是不变的。

文件内部的位置指针 用以指示文件内部的当前读写位置,每读写一次,该指针均向后移动,它不需在程序中定义说明,而是由系统自动设置的。

 

二、写字符函数fputc

fputc(字符量,文件指针); 

其中,待写入的字符量可以是字符常量或变量

例如:

fputc('a',fp);

 

说明:

1. 被写入的文件可以用写、读写、追加方式打开,用写或读写方式打开一个已存在的文件时将清除原有的文件内容,写入字符从文件首开始。被写入的文件若不存在,则创建该文件。

 

2. 每写入一个字符,文件内部位置指针向后移动一个字节。

 

3. fputc函数有一个返回值,如写入成功则返回写入的字符, 否则返回一个EOF

 

字符读写示例:

从键盘输入一行字符,写入一个文件, 再把该文件内容读出显示在屏幕上。 

#include<stdio.h>

main()
{
FILE *fp;
char ch;

if((fp=fopen("string","wt+"))==NULL)
{
printf("Cannot open file strike any key exit!");
//getch();
exit(1);
}

printf("input a string:\n");
ch=getchar();
while (ch!='\n')
{
fputc(ch,fp);
ch=getchar();
}

rewind(fp);

ch=fgetc(fp);
while(ch!=EOF)
{
putchar(ch);
ch=fgetc(fp);
}
printf("\n");

fclose(fp);
}

字符读写示例:
把命令行参数中的前一个文件名标识的文件, 复制到后一个文件名标识的文件中, 如命令行中只有一个文件名则把该文件写到标准输出文件(显示器)中。

#include<stdio.h>

main(int argc,char *argv[])
{
FILE *fp1,*fp2;
char ch;

if(argc==1)
{
printf("无文件名,请至少指定输入文件!");
//getch();
exit(0);
}

if((fp1=fopen(argv[1],"rt"))==NULL)
{
printf("不能打开输入文件 %s\n",argv[1]);
//getch();
exit(1);
}

if(argc==2) 
   fp2=stdout;
else if((fp2=fopen(argv[2],"wt+"))==NULL)
{
printf("不能打开输出文件 %s\n",argv[1]);
//getch();
exit(1);
}

while((ch=fgetc(fp1))!=EOF)
  fputc(ch,fp2);

fclose(fp1);
fclose(fp2);
}

 

 

 

字符串读写函数 fgets, fputs

一、读字符串函数fgets

fgets(字符数组名,n,文件指针); 

其中

n是一个正整数, 表示从文件中读出的字符串不超过 n-1个字符。在读入的最后一个字符后加上串结束标志 '\0' 

说明:

1. 在读出n-1个字符之前,如遇到了换行符或EOF,则结束。 // 串结束符 呢 ?

2. fgets函数也有返回值,其返回值是字符数组的首地址。

二、写字符串函数fputs

fputs(字符串,文件指针

其中 字符串可以是字符串常量,字符数组名,指针变量。

例如:

向一文件写入一串,然后读取前10字符。

 

#include <stdio.h>

main()
{
FILE *fp;
char str[128]="0123456789";
char ch;

if((fp=fopen("str","wt+"))==NULL)
{
printf("打开文件失败!");
// getch();
exit(1);
}

printf("请输入一串:");
scanf("%12s",str); // receive 12 chars, and storage 0 behind!
// scanf("%12s", tr); // receive rest chars in istream!

puts(str);
fputs(str,fp);

rewind(fp);

fgets(str, 11, fp); // read at most 10 chars, and storage 0 behind!
puts(str);

fclose(fp);
}

/*
请输入一串:01234567891011
012345678910
0123456789
Press any key to continue
*/


 

数据块读写函数 fread, fwrite

  可用来读写一组数据,如数组,结构等块数据。

fread(buffer,size,count,fp); 

fwrite(buffer,size,count,fp); 

其中

buffer是一个指针,表示存放数据块的首地址。

size 表示数据块的字节数。

count 表示要读写的数据块块数。

fp 表示文件指针。

例如:

fread(fa,4,5,fp); 其意义是从fp所指的文件中,每次读4个字节(一个实数)送入实数组fa中,连续读5次,即读5个实数到fa中。

例如:

从键盘输入两个学生数据,写入一个文件中, 再读出这两个学生的数据显示在屏幕上。

// 注意: scanf("%s%d", str, &iv); 输入串时不能有空格! 如果允许空格,使用gets。

#include<stdio.h>

struct stu
{
char name[10];
int num;
int age;
char addr[15];
}boya[2],boyb[2],*pp,*qq;

main()
{
FILE *fp;
char ch;
int i;

pp=boya;
qq=boyb;
if((fp=fopen("stu_list","wb+"))==NULL)
{
printf("Cannot open file strike any key exit!");
// getch();
exit(1);
}

printf("\ninput data\n");

for(i=0;i<2;i++,pp++)
scanf("%s%d%d%s",pp->name,&pp->num,&pp->age,pp->addr);

pp=boya;
fwrite(pp,sizeof(struct stu),2,fp);

rewind(fp);

fread(qq,sizeof(struct stu),2,fp);
printf("\n\nname\tnumber age addr\n");


for(i=0;i<2;i++,qq++)
printf("%s\t%5d%7d%s\n",qq->name,qq->num,qq->age,qq->addr);

fclose(fp);
}


 

格式化读写函数fscanffprintf

与前面使用的scanfprintf 函数的功能相似,都是格式化读写函数。区别在于 fscanf 函数和fprintf函数的读写对象不是键盘和显示器,而是磁盘文件。

格式: 

fscanf(文件指针,格式字符串,输入表列); 

fprintf(文件指针,格式字符串,输出表列); 

例如:

fscanf(fp,"%d%s",&i,s);

fprintf(fp,"%d%c",j,ch);

fscanffprintf函数也可以实现前面的操作。

格式化读写的问题: 串中不能有空格!

例如:

 

#include<stdio.h>

struct stu
{
char name[10];
int num;
int age;
char addr[15];
}boya[2], *pp;

main()
{
FILE *fp;
char ch;
int i;

if((fp=fopen("stu_list","wa+"))==NULL)
{
printf("Cannot open file strike any key exit!");
exit(1);
}

pp=boya;
for(i=0;i<2;i++,pp++)
{
printf(" student %d/2 \n", i);
scanf("%s%d%d%s",pp->name,&pp->num,&pp->age,pp->addr);
fprintf(fp,"%s %d %d %s\n",pp->name,pp->num,pp->age,pp->addr);
printf("%s %d %d %s\n",pp->name,pp->num,pp->age,pp->addr);
}

rewind(fp);
pp = boya;
for(i=0;i<2;i++,pp++)
{
printf(" student %d/2 \n", i);
fscanf(fp, "%s %d %d %s",pp->name,&pp->num,&pp->age,pp->addr);
printf("%s %d %d %s\n",pp->name,pp->num,pp->age,pp->addr);
}

fclose(fp);
}


 

文件的随机读写

  前面介绍的是顺序读写, 即读写文件只能从头开始,顺序读写各个数据。 但在实际问题中常要求只读写文件中某一指定的部分。 这就需要移动位置指针,也称文件的定位。文件定位函数主要有两个 rewind 函数和fseek函数。// 还有ftell 

rewind函数

把文件内部的位置指针移到文件首。 

rewind(文件指针); 

fseek函数

移动文件内部位置指针

fseek(文件指针,位移量,起始点); 

其中

"文件指针"指向被移动的文件。 

"位移量"表示移动的字节数,要求位移量是long型数据,以便在文件长度大于64KB // ? 超过了怎么办 )时不会出错。当用常量表示位移量时,要求加后缀"L"

"起始点"表示从何处开始计算位移量,起始点有三种:文件首,当前位置和文件尾。

 

起始点    符号    值

────────────────────

文件首      SEEK—SET  0

当前位置    SEEK—CUR  1

文件末尾   SEEK—END  2

 

例如:

把位置指针移到离文件首100个字节处。

fseek(fp,100L,0);

 

说明

fseek函数一般用于二进制文件。在文本文件中由于要进行转换,故往往计算的位置会出现错误。

文件的随机读写在移动位置指针之后,可用前面介绍的任一种读写函数进行读写。一般是用freadfwrite读写一个数据据块。

例如:

前面的例子中输出文件中存储了3个学生成绩,读出第2个学生的信息,并修改它。

...

 

文件检测函数

一、文件结束检测函数 feof

feof(文件指针)

判断文件是否处于文件结束位置,如文件结束,则返回值为1,否则为0

 

二、读写文件出错检测函数 ferror

ferror(文件指针)

检查文件在用各种输入输出函数进行读写时是否出错。 如ferror返回值为0表示未出错,否则表示有错。

 

三、文件出错标志和文件结束标志置0函数 clearerr

clearerr(文件指针);

清除出错标志和文件结束标志。

 

 


本章小结

1. C系统把文件当作一个"",按字节进行处理。

2. C文件按编码方式分为二进制文件和ASCII文件。

3. C语言中,用文件指针标识文件,当一个文件被 打开时, 可取得该文件指针。

4. 文件在读写之前必须打开,读写结束必须关闭。

5. 文件可按只读、只写、读写、追加四种操作方式打开,同时还必须指定文件的类型是二进制文件还是文本文件。

6. 文件可按字节,字符串,数据块为单位读写,文件也可按指定的格式进行读写。

7. 文件内部的位置指针可指示当前的读写位置,移动该指针可以对文件实现随机读写。

 


 

转载于:http://blog.chinaunix.net/uid-24118190-id-75229.html

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值