C语言复习之文件的操作

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.txt","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,以便下一次读写。

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值