C语言中的文件操作

   一、文件

    文件(file)一般指存储在外部介质上数据的集合,从不同的角度可对文件作不同的分类。根据存储规则可以将其分为mp3、mp4、txt、bmp、jpg、exe、rmvb等文件。从用户的角度看,文件可分为普通文件和设备文件两种:普通文件是指驻留在磁盘或其它外部介质上的一个有序数据集;设备文件是指与主机相联的各种外部设备,如显示器、打印机、键盘等。从文件编码的方式来看,文件可分为ASCII码文件和二进制码文件两种。

     ASCII文件也称为文本文件,这种文件在磁盘中存放时每个字符对应一个字节,用于存放对应的ASCII码。比如ini、h、c等文件都是文本文件。例如,数5678的文本存储形式为每个数字的ASCII码:00110101 00110110 00110111 00111000占是个字节。二进制文件是按二进制的编码方式来存放文件的。 例如, 数5678的存储形式为: 00010110 00101110只占二个字节。

二、C语言文件操作

  利用C语言进行文件操作的常用方法有三种:

(1)利用C语言的标准库进行文件操作。

(2)在UNIX环境下,可以利用UNIX系统接口,利用open,read,write等低级系统I/O进行文件操作。

(3)在Windows下可以利用fopen_s,fscanf_s等库函数的安全版本进行文件操作。  

1、利用C的标准I/O库进行文件操作  

 <1> 流与文件指针

     标准I/O库是围绕流进行的。C语言操作文件可以是字节流或者二进制流。但是C系统在处理这些文件时,并不区分类型,都看成是字符流,按字节进行处理。 输入输出字符流的开始和结束只由程序控制而不受物理符号(如回车符)的控制。 

   标准I/O库打开或创建一个文件时,我们已使一个文件流与一个文件相关联。通过fopen打开一个文件时,会返回一个指向该文件的指针称为文件指针。文件指针指向一个包含文件信息的结构,这些信息包括缓冲区的位置、缓冲区中当前字符的位置、文件的读或写状态、是否出错或是否到达文件结尾等等。文件指针用FILE*来描述

struct _iobuf {
            char *_ptr; //文件输入的下一个位置
            int   _cnt;  //剩余的字符数
            char *_base;  //缓冲区位置
            int   _flag;  //文件访问模式
            int   _file;   //文件的有效性验证
            int   _charbuf;  //检查缓冲区状况,如果无缓冲区则不读取
            int   _bufsiz;  //记录缓冲区的大小
            char *_tmpfname;  //临时文件名
        };
typedef struct _iobuf FILE;

     对于ASCII码字符集,一个字符用一个字节表示。对于国际字符集,一个字符可用多个字节表示。标准I/O文件流可用于单字节或多字节字符集。流的定向决定了读的是一个单字节或多字节的。当一个流最初被创建时,它并没有定向。如若在未定向的流上使用一个多字节I/O函数(见<wchar.h>),则流的定向设置为宽定向。若在未定向的流上使用一个单字节的I/O函数,则将该流定向为字节定向。

   fwide函数可用于设置流的定向。而freopen函数可用于清除一个流的定向。

<wchar.h>
int fwide(
   FILE *stream,
   int mode;
);

   启动一个C语言程序时,操作系统环境会打开标准输入、标准输出和标准错误3个文件,相应的文件指针分别为stdin、stdout和stderr(文件指针stdin/stdout都是FILE*类型的对象,但它们是常量而非变量,不能对它们赋值)。在大多数环境中,stdin指向键盘,而stdout和stderr指向显示器。当然也可以被重定向到文件或者管道。

   大多数系统都限制了可以同时打开的文件数。因此不使用时要及时关闭掉文件指针。

 < 2 >文件缓冲

标准I/O库提供了缓冲,目的是尽可能的减少使用read和write调用的次数。标准I/O库提供了三种类型的缓冲

1)全缓冲。在填满标准I/O缓冲后才进行实际I/O操作。

2)行缓冲。在输入输出遇到换行符时,标准I/O库执行I/O操作。

    行缓冲的限制:①因为标准I/O库用来收集每一行缓冲区的长度是固定的,所以只要填满了缓冲区,那么即使还没有写一个换行符,有进行I/O操作。②任何时候只要通过标准I/O库要求从一个不带缓冲的流或者一个行缓冲的流得到输入数据,那么就会冲洗所有的缓冲输出流。

3)不带缓冲。标准I/O库不对字符进行缓冲存储。

系统默认的缓冲:

1)标准错误不带缓冲

2)若是指向终端的设备的流,则进行行缓冲

3)否则进行全缓冲

[1] 更改缓冲类型和大小

(1) setbuf

1) 函数原型

void setbuf(
   FILE *stream,
   char *buffer 
);
 
2)参数说明

stream 为已打开的文件指针,并且还没有被读或者写

buffer为缓冲区的地址。缓冲区的大小为BUFSIZE(该常量定义在<stdio.h>中)。

buffer为NULL时,将关闭缓冲

3)说明

通常调用该函数后流就是全缓冲的,但是如果流与一个终端设备相关,那么某些系统也可将其设置为行缓冲的。

(2) setvbuf

1)函数原型

int setvbuf(
  FILE* stream,
  char* buffer,
  int mode,
  size_t size 
);
2)参数

buffer:如果是全缓冲或者行缓冲则需要指定缓冲区buffer,如果没有指定则标准库会自动为该流分配适当的长度的缓冲区(BUFFSIZ);如果是不带缓冲则忽略buffer

mode:可为_IOFBF 全缓冲;_IOLBF 行缓冲;_IONBF 不带缓冲

size:如果是全缓冲或者行缓冲则2 <= size <= INT_MAX (2147483647);如果不带缓冲则忽略size

3)返回值

成功是返回0;若出错返回非0.

4)示例

#include <stdio.h>

int main( void )
{
   char buf[1024];
   FILE *stream1, *stream2;

   if( ((stream1 = fopen( "data1", "a" )) != NULL) &&
       ((stream2 = fopen( "data2", "w" )) != NULL) )
   {
      if( setvbuf( stream1, buf, _IOFBF, sizeof( buf ) ) != 0 )
         printf( "Incorrect type or size of buffer for stream1\n" );
      else
         printf( "'stream1' now has a buffer of 1024 bytes\n" );
      if( setvbuf( stream2, NULL, _IONBF, 0 ) != 0 )
         printf( "Incorrect type or size of buffer for stream2\n" );
      else
         printf( "'stream2' now has no buffer\n" );
      fclose(stream1);
	  fclose(stream2);
   }
}
运行结果:


[ 2 ] 冲洗缓冲区

在标准I/O库中,冲洗意味着将缓冲区的内容写到磁盘上(缓冲区可能只是部分填满的)。在终端驱动程序方面冲洗表示丢弃已存储在缓冲区中的数据。

(1)fflush

int fflush( 
   FILE* stream 
);
若成功返回0,若出错返回EOF。

< 3 > 利用标准I/O库进行文本文件的读写

   之前的博文对利用I/O库进行文本文件的打开,逐个字符读写以及逐行读写进行了详细分析。
   利用标准I/O库对文本文件进行读写

<4>C语言中的二进制I/O

      链接:C语言中的二进制I/O:fread、fwrite

2、UNIX环境下,利用UNIX系统接口进行文件I/O操作

   链接:UNIX 系统文件I/O

3、Windows环境下利用fopen_s,fscanf_s等库函数的安全版本进行文件操作 

   windows中的fopen_s等安全增强函数

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值