您的位置:首页 > 编程语言 > C语言/C++

C语言复习之文件的操作

2013-05-04 18:20 260 查看
C语言把文件看作是一个字符(或字节)的序列,即由一个个字符或字节的数据顺序组成。一个输入输出流就是一个字符流或字节流。
   数据在磁盘的存储:1.字符存储2.按字节存储(二进制文件)

   文件缓冲区:ANSI C标准采用“缓冲文件系统”处理数据文件。

 

                                                         输出文件缓冲区

                                                                                                                  输出

             程序数据区                                                                                                            磁盘

            

                                                                                                                   输入

                                                         输入文件缓冲区

 

当缓冲区满了,将数据从缓冲区输入或输出

C中的缓冲文件系统

 

1.      文件类型指针:

缓冲文件系统,关键是文件指针。每个被使用的文件都在内存中开辟一个响应的文件信息区,用来存放文件的相关信息(如,文件的名字、文件的形态以及当前位置等)。

这些信息保存在一个结构体变量中。

该结构体由系统声明(在某个头文件中,如stdio.h)

Typedef struct

{

  short level;      //缓冲区”满”或”空”的状态

  unsignedflags;   //文件状态标志

  char fd;         //文件描述符

  unsigned char hold;//如缓冲区无内容不读取字符

  short bsize;      //缓冲区大小

  unsigned char*buffer;//数据缓冲区的位置

  unsigned char*curp;//指针当前的指向

  unsigned istemp;   //临时文件指示器

  short token;      //用于有效性检查

}FILE;

 

一般不用FILE定义变量,而是定义FILE类型的指针变量来指向文件的信息区。

通过该文件信息区的信息就能访问这个文件。(这些信息是在打开文件时由系统根据文件的情况自动放入的,用户不必过问)

   因此,通过文件指针变量能够找到预支相关联的文件。

 

 FILE *fp;  fp指向某个文件在内存中的文件信息区。

 

2.      打开和关闭文件:

 

打开文件后才能对文件进行读写。打开文件就是:为文件建立相应的文件信息区(存放文件的信息)和文件缓冲区(暂存文件的输入输出信息)。

 

2.1  fopen

调用方式:

 fopen(文件名,使用文件的方式);

如:FILE *fp;

fp=fopen(“file1”,”r”);

调用正确,返回文件在文件信息区的地址,错误,返回NULL

 

使用文件的方式:

文件使用方式
含义
如果指定文件不存在
“r”(只读)

为了输入数据,打开已经存在的文件

出错
“w”(只写)

为了输出数据,打开一个文本文件

建立一个新的文件

“a”

向文本尾添加数据

出错

“rb”(只读)

为了输入数据,打开一个二进制文件

出错

“wb”

 

建立一个新文件

“ab”(追加)

 

出错

“r+”(读写)

 

出错

“w+”(读写)

 

建立新文件

“a+”(读写)

 

 

“rb+”(读写)

 

 

“wb+”

 

建立新文件

“ab+”

 

 

 

  如果不能实现“打开”任务fopen会返回出错信息(NULL),出错原因:

文件不存在、磁盘出故障、磁盘满等

 

常见的打开文件的方法:

  if(fp=fopen(“file1”,”r”)==NULL)

{

   printf(“can’t open thefile\n”);

   exit(0);  //表示正常退出

}

 

程序中可以使用的3个标准的流文件:标准输入流(向终端输入-键盘)、标准输出流(向终端输出-屏幕)、标准出错输出流(向终端输出错误)

系统已经对这三个文件制定了与终端的对应关系。

程序开始运行时系统自动打开这三个标准流文件,因此不需要用fopen打开这三个文件,系统定义了3个文件指针变量stdin、stdout、stderr

如果程序中指定从stdin所指的文件输入数据,就是从终端键盘输入数据

2.2用fclose函数关闭数据文件

    fclose(文件指针);

   成功完成关闭操作,返回0;否则返回-1

 

当使用完一个文件,要关闭它,防止被误用。“关闭”就是撤销文件信息区和文件缓冲区,是文件指针不再指向该文件。此后不能通过该指针引用该文件

用fclose关闭文件,将文件缓冲区的数据输入或输出,然后才撤销文件信息区(有的系统会自动在程序关闭时完成该操作)。

 

3.      顺序读写数据文件。

顺序读写文件需要用库函数实现。

3.1向文件读写字符

fgetc(fp); 从文件读取一个字符   读成功返回读的字符,否则返回文件结束标志(E0F即-1)

fputs(ch,fp);向文件写入字符ch   ::

 #include<stdio.h>
#include<stdlib.h>
intmain()
{
FILE*fp;
charch;
if((fp=fopen("1.txt","w+"))==NULL)
{
printf("Can'topenthefile\n");
exit(0);
}

ch=getchar();
while(ch!='#')
{
fputc(ch,fp);
ch=getchar();
}

fclose(fp);
return0;
}
 

 

将一个文件中的信息复制到另一个文件中

 #include<stdio.h>
#include<stdlib.h>

intmain(void)
{
FILE*in,*out;

if((in=fopen("1.txt","r"))==NULL)
{
printf("Can'topenthefile\n");
exit(0);
}
if((out=fopen("2.t
4000
xt","w"))==NULL)
{
printf("Can'topenthefile\n");
exit(0);
}

while(!feof(in))
fputc(fgetc(in),out);

fclose(in);
fclose(out);
return0;
}
 

 

3.2 向文件写入一个字符串。

fgets(str,n,fp);

函数原型:char *fgets(char*str,int n,FILE *fp);

n是得到的字符个数,实际上只是读了n-1个字符,然后在最后加’\0’,把它们放入字符串str中。如果在读完n-1个字符前遇到换行符’\n’或文件结束标志EOF,读入即结束。执行成功返回str数组元素首地址,如果一开始就遇到文件结尾或读数据出错返回NULL

 

fputs(str, fp);

函数原型:int fputs(char *str,FILE*fp);

字符串末尾的’\0’不输出,成功返回值为0,失败返回EOF

 

feof(fp):

feof(fp)有两个返回值:如果遇到文件结束,函数feof(fp)的值为非零值,否则为0

 

(C语言中如何表示路径,如在windows C:\ 在C语言中要表示为C:\\,因为C语言把\作为转义字符)

 

 

3.3格式化的方式读写文件。需要不断的进行格式转换,花费时间多。经常采用二进制方式读写

 

3.4用二进制方式向文件读写一组数据:

 在程序中有时需要一次输入输出一组数据(数组或结构体变量的值),C语言允许fread从文件读入一个数据块,用fwrite向文件写入一个数据块。读写都是以而仅是的形式,节省时间。

调用形式:fread(buffer,size,count,fp);

         fwrite(buffer,size,count,fp);

  buffer:是一个地址。对fread来说是存放从文件读出数据的存储区的地址

                    对fwrite来说是把从此地址开始的存储区的数据向文件输出

 这个地址是起始地址

  size:要读的字节数

  count:要读多少个数据项

  返回值是数据项的个数

 

具体用法来看看下面这个例子:

输入学生的信息,读出来:

#include<stdio.h>
#include<stdlib.h>

#defineSIZE3

structStudent_type
{
charname[20];
intnum;
intage;
};

intmain()
{
voidsave();
voiddisplay();

save();
display();

return0;
}

voidsave()
{
FILE*fp;
structStudent_typestud[SIZE];
inti;

if((fp=fopen("stu.dat","wb"))==NULL)
{
printf("Can'topenthefile\n");
exit(0);
}

printf("Pleaseinputthestudents'info:\n");
for(i=0;i<SIZE;i++)
scanf("%s%d%d",stud[i].name,&stud[i].num,&stud[i].age);

if(fwrite(&stud[0],sizeof(structStudent_type),5,fp)!=5)
{
printf("Can'twrite\n");
exit(0);
}

fclose(fp);
}

voiddisplay()
{
structStudent_typestud[SIZE];
FILE*fp;
inti;

if((fp=fopen("stu.dat","rb"))==NULL)
{
printf("Can'topenthefile\n");
exit(0);
}

for(i=0;i<SIZE;i++)
{
if(fread(&stud[i],sizeof(structStudent_type),1,fp)!=1)
{
printf("Readerror!\n");
exit(0);
}
printf("%s%d%d\n",stud[i].name,stud[i].num,stud[i].age);
}
fclose(fp);
}
如果要将sut_list.dat的数据读入到stu.dat中需要加入这个函数:

voidload()

{

   FILE*fp;

   structStudent_typestud[SIZE];

   inti;

 

   if((fp=fopen("stu_list.dat","rb"))==NULL)

   {

       printf("Can'topenthefile\n");

       exit(0);

   }

   

    for(inti=0;i<SIZE;i++)

   {

       if(fread(&stud[i],sizeof(structStudent_type),1,fp)!=1)

       {

           if(feof(fp))

           {

               fclose(fp);

               return;

           }

        printf("filereaderror\n");

       }

       

    }

   fclose(fp);

}

 

多了一步,判断文件是否已经读完了。

 

4.随机读写文件

4.1文件位置标记

   每个文件都有一个文件位置标记。顺序读写时:读一个字符,文件为位置标记自动下移一个字符,直到文件结束。

   随机读写文件,关键在控制文件位置标记。这样可以在任意位置读写了

 

4.2文件位置标记的定位

  4.2.1 用rewind函数使文件位置标记重新回到文件开头,此函数没有返回值

       rewind(fp);

 4.2.2 用fseek函数改变文件位置标记

     调用形式:fseek(文件类型指针,位移量,起始位置);

     位移量是long型整数

     起始位置:

     

起始点

名字

用数字代表

文件开头

SEEK_SET

0

文件当前位置

SEEK_CUR

1

文件末尾位置

SEEK_END

2

 

 4.2.3 用ftell函数测定文件位置标记的当前位置:返回相对于文件开头位移量,调动出错返回-1L

 

实现随机读写的一个例子:

#include <stdio.h>
#include <stdlib.h>

#define SIZE 3

struct Student_type
{
char name[20];
int num;
int age;
}stud[SIZE];

int main()
{
FILE *fp;
int i;
if((fp=fopen("stu.dat","rb"))==NULL)
{
printf("Can't open file\n");
exit(0);
}

for(i=0;i<3;i+=2)
{
fseek(fp,i*sizeof(struct Student_type),0);
fread(&stud[i],sizeof(struct Student_type),1,fp);
printf("%s %d %d\n",stud[i].name,stud[i].num,stud[i].age);

}

fclose(fp);

return 0;
}


4.5 文件读写的出错检查

  4.5.1 ferror函数

     在调用各种输出函数(fputc,fread等)如果出错,除了返回值有所反应外,还可以用ferror函数检查错误

返回0未出错,返回非0值出错。

对同一个文件每一次调用输入输出函数都会产生一个新的ferror函数值,因此在调用完一个输入输出函数时要立即检查ferror函数值,否则信息会丢失。

再执行fopen函数时,ferror初始值自动置为0

 

4.5.2clearerr函数。将文件错误标志和文件结束标志自动置为0,以便下一次读写。

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C