[C语言基础]文件操作及相关函数

一 文件

1 C文件概述

        文件( file ) 是指存储在外部介质上数据的集合。操作系统则是以文件为单位对数据进行管理的.
        C 语言中文件是流式文件,即文件是一个字节流或二进制流.并以字节为单位进行存取.
        根据文件中数据的存储方式,C 语言的文件可分为:
        文本文件(ASCII码文件)和二进制文件。

1. 文本文件
        文件中每一个字符占一个字节,按其ASCII码存放。
        特点:  可直接阅读,也可按字符逐个处理。但占用存储空间较大,同时需要额外的转换时间.
            转换
        数据写入文件时:二进制码转换成ASCII码
             数据读入内存时:ASCII码转换成二进制码
2.   二进制文件
        二进制文件是将数据按其在内存中的存放形式直接存入文件中.
        特点:节省存储空间和转换时间,但不能直接阅读。一般用于存放数据或中间结果,以提高处理速度。

  C 程序中对文件的处理是通过调用系统提供的输入输出函数来实现的。
   它把所有的外部设备都作为文件对待,这样的文件也叫设备文件。在 C 语言中把一般磁盘文件和设备文件都作为相同的逻辑文件对待,对它们的输入输出采用相同的方法进行。
   C 语言中可采用“缓冲文件系统”和“非缓冲文件系统”来处理文件.
缓冲文件系统:
       系统自动在内存区为每一个正在使用的文件开辟
一个缓冲区,数据的输入和输出都先经过缓冲区。
       新标准C中规定,只采用“缓冲文件系统”。

2.文件类型指针

    对文件的处理是通过系统自动定义的文件结构体类型来进行的。它在“stdio.h”文件中。如:
    typedef   struct
            {   
         int   fd;           /* 文件号*/
               int   cleft;         /* 缓冲区中剩下的字节*/
               int   mode;          /* 文件操作模式*/
               char  *nextc;      /*下一个字节位置*/
               char  *buff;      /* 文件缓冲区位置*/
            } FILE ;
        文件结构体一般习惯取名为 FILE 。
        文件打开时,系统自动建立该文件的文件结构体,关闭文件后,该文件的结构体就被释放。

C语言对文件的操作是通过文件指针来实现的。而文件指针是通过文件结构体类型来定义的。如:
FILE    *fp  ;
        fp 是一个指向 FILE 结构体类型的指针变量(简称文件指针 )。通过 fp 就能够打开和关闭与之相关的文件。
        另外,C 语言中有三个标准文件指针由系统分配和控制,用户不能控制其开闭。
    标准输入文件:           分配给键盘.         文件指针:    stdin
    标准输出文件:           分配给显示器.     文件指针:    stdout
    标准错误输出文件:   分配给显示器.     文件指针:    stderr
    程序开始运行时,系统自动打开三个标准设备文件.

二 函数

1.fopen ( )函数

    用 fopen ( ) 函数来打开文件.
    格式:        FILE    *fp  ;
                      fp = fopen(文件名, 使用文件方式);
    文件名:(1)可以是用双引号括起来的文件名字。
                  (2)也可以是存放文件名字符串的首地址。
        fopen 函数的返回值是所要打开文件的指针。
    如:            FILE   *fp  ;
                fp=fopen(“f1.c”,“r”);
    被打开的文件名前面可以指明盘符和路径。如:
                  fp=fopen(“d:\\user\\stu.dat”,“r”);

说明:
   1. 使用方式: 常见的有 “r”,“w”,“rb”,“wb”,“ r+”,“w+” 等。
   2. 文件使用方式说明:
    (1) “r”方式:  用于打开一个已存在的文本文件 。    
               只读,打开时,文件位置指针自动指向文件
               开头。
    (2) “w”方式: 该方式打开的文本文件。
               只写,如不存在该文件,则新建一个指定的
               文件名的文件;如该文件已存在,则打开时
                           先删除该文件,然后重建立一个新文件.
    (3) “a” 方式: 该方式用于向文本文件
               末尾添加数据。
               文件打开时,位置指针自动指向文件末尾。
               如文件不存在,则创建一个新文件。

    (4) “r+”,“w+”,“a+” 方式:
        这三种方式打开的文件均可进行读写操作。
         r+:  先读后写被打开的文件应存在,位置指针指向文件开头。如原文件中有内容时,则写入的内容会覆盖原文件内容。
        w+:先写后读。用该方式打开的文件,其内容全部丢失,指针指向文件开头.
        a+: 用该方式打开的文件内容保留。位置指针自动指向文件末尾,可以追加数据,然后再读入数据。
        另外还有:  rb , wb , ab , rb+ , wb+ , ab+ 等方式,其含义同前述,只是用于二进制文件而已.
        注意:不同的 C 系统,在文件打开方式的的表示上可能不相同,具体随所用的系统而定。

3. 正常打开文件时,fopen 函数返回指向该函数的指针。如不能打开文件,返回一个空指针值NULL。NULL在stdio.h 文件中已定义为0。
     *常用固定格式:      
             FILE    *fp;
             if((fp=fopen(“f1.c”,“r”))==NULL)
             {    
                   printf(“Cannot open this file\n”);
                   exit(0);
             }
       其中exit函数的作用是关闭文件,终止正在调用的过程。exit(0)是正常退出程序,exit(!0)是表示某种类型错误。

2.fclose()关闭文件

    用 fclose 函数来关闭文件.
        格式: fclose ( 文件指针 ) ;
     如:     fclose(fp);
                 fclose 函数也带回一个返回值,正常关闭文件时返回值为 0, 反之返回值为非0。 可以用ferror函数来测试.

3.fputc()函数

   格式:  fputc(ch,fp)
      作用:  将一个字符(ch)输出到 fp所指向的文件中去。
      返回值:成功:则返回值就是所输出的字符;
                      失败:则返回EOF符号常量.  stdio.h 中 EOF
                                  被定义为-1。
        前面所讲的 putchar 函数实质上是由 fputc 函数派生出来的。
         #define  putchar(c)   fputc(c, stdout)

4. fgetc 函数

    格式:  ch=fgetc(fp)
      作用: 从指定的文件中读入一个字符(对文本文件)或一个字节的数据(对二进制文件),该文件必须是以读或读写方式打开的。
      返回值:正常请况下,fgetc 函数返回一个字符并赋给 ch。如遇文件结束符,则返回一个文件结束标志 EOF。

说明:  
    文本文件:    由于字符的ASCII码不可能为-1,故
                            EOF定义为 -1是合适的。
    二进制文件:数据的值有可能是-1,以EOF作为文件结束则不合适。因此,常用 feof 函数来测试文件是否真正结束。  
feof函数使用              
    使用格式:   feof(fp)
    返回值:     文件结束,则返回值为1,反之为 0。
    这种判别方法对二进制文件和文本文件均适用。
    如前例中的 while 语句可改为:   
                         while(!feof(fp))

5.fwrite和fread函数

1.1fwrite函数:

把结构体数据写入磁盘使用fwrite函数;

格式为:fwrite(buffer,size,count,fp);

其中buffer为待写入磁盘数据的结构体首地址;

size:一次写入的字节数,即sizeof(struct student);

count:为写入count次size大小的数据;

fp:文件指针,指向待写入磁盘文件的地址;

代码段:

struct student
    {
        char    name[20];
        int        num;    
        int        year;
        int        score;
}stu[2];

.....
if(fwrite(&stu[i],sizeof(struct student),1,out)!=1)
{
	printf("Error write\n");
}
printf("sucess write %d\n",i+1);

....

测试分析:

写入几个结构体数据后,打开保存进磁盘文件的数据和待写入的数据不一致;

1:学生的数据是ASCII码,送入内存时,由内存以“wb”方式输出到磁盘文件时不发生字符阻转化,即按内存中存储形式原样输出到磁盘文件上;

2:fwire和fread函数一般用于二进制文件的输入和输出。因为它们是按数据块的长度处理输入输出的,在字符发生转换时,可能出现与原设想的不同的结构;比如用scanf函数输入的话,空格也会存入stu[i]中,显然不符;

明天使用fread函数读出已写入磁盘文件的数据,看看是什么妖魔鬼怪。

1.2fread函数

格式为:fread(buffer,size,count,fp);

其中buffer为待读入磁盘数据的结构体首地址;

size:一次写入的字节数,即sizeof(struct student);

count:为写入count次size大小的数据;

fp:文件指针,指向待写入磁盘文件的地址;

代码段:

    for(i=0;i<2;i++)
    {
    //    while (!feof(fp))//feof返回0 说面未结束
    //    {
            //ch = fgetc(fp);
            //putchar(ch);其中未必全是char 型数据,这是结构体,所以不能使用fgetc+puchar        
    //    }
        fread(&stu[i],sizeof(struct student),1,fp);//使用fp指向要读的文件,&stu[i] 是读出的首地址
        printf("%s %d %d %d",stu[i].name,stu[i].num,stu[i].year,stu[i].score);
        printf("\n");
    }

对于读结构体数据使用fread函数,而不能使用fgetc+puchar;

测试分析:

6:fprintf 和 fscanf 函数

      二者叫格式化读写函数。其作用与 printf  和 scanf 函数相当 ,只是后者以终端(显示器,键盘)为对象。前者是以磁盘文件为读写对象。

格式:  fprintf( fp, 格式字符串, 输出表列);
         fscanf( fp, 格式字符串, 输入表列);

  如:

 int  i=3;
 float  t=4.5;
 fprintf ( fp,“%d,%6.2f ”, i, t );

则是将字符串 3 , 4.5 写到 fp 指向的磁盘文件中.
 同样:

     fscanf (fp,“%d,%f”, &i, &t );

说明:
        用 fprintf  和 fscanf 函数对磁盘文件读写, 输入时要将ASCII码转换为二进制形式。在输出时又要将二进制形式转换为字符,因此比较费时。不利于内存与磁盘间频繁交换数据。

7.其它读写函数

  1.putw 和 getw 函数

        作用: 从指定的磁盘文件中读写一个字(整数)
        如:  putw(10,fp);
                i =getw(fp);
   2. fgets 和  fputs 函数
       作用: 从指定的磁盘文件中读写一个字符串.
       如:    char   str[100];
               fgets ( str,n,fp);
       即从 fp 指向的文件中读入n-1个字符,并放入数组 str
中。如在读入 ( n-1) 个字符结束之前遇到换行符或EOF,
读入即结束.
   同样:   fputs(“China”,fp);
   或者:   fputs(str,fp);

三 文件的定位

在顺序读写文件时,文件中的位置指针是自动变化的,即读写完一个字符后,该位置指针自动移向下一个字符位置.可以用函数来强制是位置指针指向其它位置。

1. rewind 函数

作用: 使文件位置指针重返文件的开头.此函数无返回值.

格式:   rewind(fp);

        main ( )
        {    
             FILE  *fp1 , *fp2 ;
             fp1=fopen( “file1.c ”, “r”);
             fp2=fopen( “file2.c ”, “w”);
             while( !feof (fp1))   putchar(fgetc(fp1));
             rewind( fp1);
             while( !feof(fp1))    fputc(fgetc(fp1),fp2);
             fclose(fp1);   
	             fclose(fp2);
        }

2. fseek 函数和随机读写

    顺序读写: 如果文件位置指针是按字节位置顺序移动。
    随机读写: 如果文件位置指针能按需要移动到任意位置。
    格式:   fseek ( 文件类型指针 ,   位移量 ,        起始点 )  
                   文件开始                SEEK_SET       用 0 表示.
    起始点:  文件当前位置            SEEK_CUR     用 1 表示
                   文件末尾                SEEK_END      用 2 表示
    位移量: 起始点为基点,向前移动的字节数。要求为长整型数据,以使文件大于 64 k 时不会出问题.
        如:    fseek ( fp , 100L  , 0 )     
                 fseek ( fp , 50L  , 1 )
                 fseek ( fp , -10L  , 2 )
     说明:  fseek 函数一般多用于二进制文件。对于文本文件,由于存在字符转换问题,因此位置计算可能引起混乱。

/*例 13.5 磁盘文件上有4个学生的数据,将 1, 3  个学生数据输入计算机,并在屏幕上显示出来.*/

代码段:

void test13_7()
{
	int i;
	FILE *fp;
	if((fp=fopen("stulist","rb"))==NULL)
	{
		printf("Cannot open this file\n");
		exit(0);
	}
	for(i=0;i<4;i+=2)
	{
		fseek(fp,i*sizeof(struct student),0);
		fread(&stu[i],sizeof(struct student),1,fp);
		printf("%s %d %d %d",stu[i].name,stu[i].num,stu[i].year,stu[i].score);
		printf("\n");
	}
	fclose(fp);
	printf("\n");
}

测试及分析:

3. ftell 函数

作用: 获取文件位置指针的当前位置(用相对于文件开头的位移量来表示,单位是 字节 )
       格式:     ftell(fp);
       正常情况下 ftell 函数的返回值就是位置指针的位置。如返回值为-1L , 则表示出错.

   main( )
   {    
         long   int   i;
         FILE  *fp;
         fp = fopen ( “stud_dat”, “ rb ”);
         ……
         i = ftell ( fp );  
         if ( i = = -1L )
             printf(“error \n”);
         else   
             printf(“%ld ”,i );
         ……. 
    }

四 出错的检测

1. ferror 函数

           调用各种输入,输出函数(如: putc , getc , freed , fwrite等)时,函数返回值可以反映出是否出错。也可以用ferror函数来检测。
        格式:     ferror( fp );
        如ferror的返回值为0(假),则表示未出错。反之,则出错。
说明:
        1. 在执行 fopen 函数时 , ferror 函数的值自动置为 0 。   
        2. 对同一文件,每一次调用输入或输出函数,均产生一个新的 ferror 函数值。因此,在调用一个输入或输出函数后。应立即检测 ferror 函数值。否则,信息会丢失.

                fputc(ch,fp);   
                if( ferror( fp )!=0); 
                      printf(“error \n”);
                  ……. 
                 fgetc(fp);                  
                 if (ferror( fp )!=0); 

2. clearerr 函数

 格式:         clearerr(fp);
        作用:  使文件错误标志和文件结束标志置为 0 。
        在调用一个输入或输出函数时如出错,ferror 函数的值为非零值,如此时调用clearerr 函数,则 ferror 函数的值变成 0 。
        另外: 只要出现错误标志,就一直保留,直到对同一文件调用了:
         (1) clearerr 函数或 rewind 函数。
         (2) 任何其它一个输入输出函数。
               如: putc , getc , freed , fwrite 等.

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值