目录
键盘、显示器、打印机、磁盘驱动器等逻辑设备, 其输入输出都可以通过文件操作管理的方法来完成。文件输入输出函数有两类关于文件的函数。一类称做标准文件函数也称缓冲型文件函数, 这是 ANSI 标准定义的函数; 另一类叫非标准文件函数, 也称非缓冲型文件函数。
在了解文件操作函数之前,需知道一个基本概念:
流(stream)和文件(file) ,标准库为编程者和被访问的设备之间提供了一层抽象的东西, 称之为"流", 而将具体的实际设备叫做文件 。 流看作是一个逻辑设备, 具有相同的行为。因此, 其可用来进行文件写的函数也同样可以用来进行打印机的写入。一般有两种性质的流: 文字流( text stream)和二进制(binary stream)。对磁盘访问来说就是文本文件和二进制文件。
主要包括文件的打开、关闭、读和写等函数,提供顺序读写函数和随机读写函数两组函数。
1.fopen()函数用于打开文件,通常包含在
文件指针FILE 实际上FILE 是一个新的数据类型。它是基本数据类型的集合的结构指针。就是一个包括了文件管理有关信息的数据结构, 即在打开文件时必须先定义一个文件指针。
fopen打开文件的函数,返回一个文件指针,其中形式参数有两个,均为字符型变量(字符串数组或字符串指针)。 fopen()函数中第一个形式参数表示文件名, 可以包含路径和文件名两部分。 如: "1.txt" "C:\\myfile\\1.txt" 。 第二个形式参数表示打开文件的类型。关于文件类型的规定参见下表
如果要打开一个 C:\\myfile子目录中, 文件名为 1.dat的二进制文件,可写成: fopen("c:\\myflie\\1.dat", "rb")。如果成功的打开一个文件, fopen()函数返回文件指针, 否则返回空指针 (NULL)。由此可判断文件打开是否成功。
2. fclose()函数
fclose()函数用来关闭一个由fopen()函数打开的文件 , 其调用格式为: int fclose(FILE *stream); 该函数返回一个整型数。当文件关闭成功时, 返回 0, 否则返回一个非零值。 可以根据函数的返回值判断文件是否关闭成功 。
1. 文件的顺序写函数 fprintf()、fputs()和 fputc()函数
函数 fprintf()、fputs()和 fputc()均为文件的顺序写操作函数, 其调用格 式如下:
上述三个函数的返回值均为整型量。fprintf() 函数的返回值为实际写入文件中的字节个数(字节数)。如果写错误,则返回一个负数; fputs()函数返回 0 时表明将 string 指针所指的字符串写入文件中的操作成功,返回非 0 时,表明写操 作失败;fputc()函数返回一个向文件所写字符的值,此时写操作成功,否则返 回 EOF(文件结束结束其值为-1, 在 stdio.h 中定义)表示写操作错误。 fprintf( ) 函数中格式化的规定与 printf( ) 函数相同,所不同的只是 fprintf()函数是向文件中写入。而 printf()是向屏幕输出。
2. 文件的顺序读操作函数 fscanf()、fgets()和 fgetc()函数
函数 fscanf()、fgets()和 fgetc()均为文件的顺序读操作函数, 其调用格式 如下:
fscanf()函数的用法与scanf()函数相似,只是它是从文件中读到信息。 fscanf()函数的返回值为 EOF(即-1),表明读错误,否则读数据成功;fgets()函数从文件中读取至多n-1个字符(n 用来指定字符数),并把它们放入string 指向的字符串中, 在读入之后自动向字符串未尾加一个空字符,读成功返回 string 指针,失败返回一个空指针;fgetc()函数返回文件当前位置的一个字符,读错误时返回EOF。
1.有时需要直接读取文件中间某处的信息,若用文件的顺序读写必须从文件 头开始直到要求的文件位置再读,这显然不方便。标准库提供了一组文件的随机读写函数,即可以将文件位置指针定位在所要求读写的地方直接读写。
文件的随机读写函数如下:
fseek()函数的作用是将文件的位置指针设置到从fromwhere 开始的第 offset 字节的位置上,其中 fromwhere(fromwhere,文件位置指针起始计算位置 ) 是下列几个宏定义之一:
offset 是指文件位置指针从指定开始位置(fromwhere到指出的位置)跳过的字节数。它是一个长整型量, 以支持大于64K字节的文件。fseek()函数一般用于对二进制文件进行操作。当 fseek()函数返回 0 时表明操作成功,返回非0 表示失败。
fread()函数是从文件中读 count 个字段,每个字段长度为size个字节,并把它们存放到 buf 指针所指的缓冲器中。
fwrite()函数是把 buf 指针所指的缓冲器中,长度为size 个字节的 count 个字段写到 stream 指向的文件中去。 随着读和写字节数的增大,文件位置指示器也增大, 读多少个字节,文件位置指示器相应也跳过多少个字节。读写完毕函数返回所读和所写的字段个数。
ftell()函数返回文件位置指示器的当前值,这个值是指示器从文件头开始 算起的字节数,返回的数为长整型数,当返回-1 时,表明出现错误。
2.缓存区刷新函数fflush():
当用标准文件函数对文件进行读写操作时, 首先将所读写的内容放进缓冲区, 即写函数只对输出缓冲区进行操作,读函数只对输入缓冲区进行操作。例如向一个文件写入内容,所写的内容将首先放在输出缓冲区中, 直到输出缓冲区存满或使用 fclose()函数关闭文件时,缓冲区的内容才会写入文件中。若无 fclose() 函数,则不会向文件中存入所写的内容或写入的文件内容不全。有一个对缓冲区进行刷新的函数,即 fflush(),其调用格式为:
int fflush(FILE *stream);
该函数将输出缓冲区的内容实际写入文件中,而将输入缓冲区的内容清除掉。
feof()和rewind()函数 , 这两个函数的调用格式为:
int feof(FILE *stream);
int rewind(FILE *stream);
feof()函数检测文件位置指示器是否到达了文件结尾,若是则返回一个非 0 值,否则返回 0。这个函数对二进制文件操作特别有用,因为二进制文件中,文 件结尾标志EOF也是一个合法的二进制数,只简单的检查读入字符的值来判断文件是否结束是不行的。如果那样的话,可能会造成文件未结尾而被认为结尾,所以就必须有 feof()函数。 例如下面的这条语句是常用的判断文件是否结束的方法。
while(!feof(fp)) fgetc(fp);
rewind()函数用于把文件位置指示器移到文件的起点处,成功时返回 0,否则返回非 0 值。
这类函数最早用于UNIX 操作系统,ANSI 标准未定义,但有时也经常用到,因此大多编译器也支持这些函数。它们的头文件为io.h。 一、文件的打开和关闭
1.open()函数
open()函数的作用是打开文件,其调用格式为:
int open(char *filename, int access);
该函数表示按 access 的要求打开名为 filename 的文件, 返回值为文件描述字,其中 access 有两部分内容:基本模式和修饰符,两者用" |"("或")方式连接。 修饰符可以有多个, 但基本模式只能有一个。access的规定如下表:
open()函数打开成功, 返回值就是文件描述字的值(非负值), 否则返回-1。
2.close()函数
close()函数的作用是关闭由open()函数打开的文件,其调用格式为:
int close(int handle);
该函数关闭文件描述字 handle 相连的文件。
1. read()函数
read()函数的调用格式为:
int read(int handle, void *buf, int count);
read()函数从handle(文件描述字)相连的文件中,读取 count 个字节放到 buf 所指的缓冲区中,返回值为实际所读字节数,返回-1表示出错。返回 0 表示文件结束。
2. write()函数
write()函数的调用格式为:
int write(int handle, void *buf, int count);
write()函数把 count 个字节从 buf 指向的缓冲区写入与 handle 相连的文件中,返回值为实际写入的字节数。
1. lseek()函数
lseek()函数的调用格式为:
int lseek(int handle, long offset, int fromwhere);
该函数对与 handle 相连的文件位置指针进行定位,功能和用法与fseek() 函数相同。
2. tell()函数
tell()函数的调用格式为:
long tell(int handle);
该函数返回与 handle 相连的文件现生位置指针,功能和用法与 ftell()相同。
在 C++ 中,有一个 stream 这个类,所有的 I/O 都以这个“流”类为基础的,包括我们要认识的文件 I/O,也包括从stream类派生出来的istream、ostream、fstream、iostream、ifstream等等, stream 这个类有两个重要的运算符:
1、插入器(<<)
向流输出数据。系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<"hello world";就表示把字符串"hello world"输出到标准输出流。
2、析取器(>>)
从流中输入数据。系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin>>x;就表示从标准输入流中读取一个指定类型(即变量 x 的类型)的数据。
在 C++ 中,对文件的操作是通过 stream 的子类 fstream(file stream)来实现的。
在 fstream 类中,有一个成员函数 open(),就是用来打开文件的,其原型是:
void open(const char* filename,int mode,int access);
参数:
打开文件的方式在类 ios(是所有流式 I/O 类的基类)中定义,常用的值如下:
可以用"|"(“或”)把以上属性连接起来,如 ios::out|ios::binar。
打开文件的属性取值是:
可以用“或”(“|”)或者“+”把以上属性连接起来 ,如 3 或 1|2 就是以只读和隐含属性打开文件。
如果你已经创建一个流文件对象,但你没有进行打开文件操作,像这样:
ifstream File; //也可以是一个 ofstream
这样,我们就拥有一个文件句柄。 如果在你的程序的某处,你可能需要知道当前的句柄是否关联了一个已经打开的文件,那么你可以用 is_open()来进行检测。如果文件没有打开,它将返回 0 (false);如果文件已经打开,它将返回 1 (true)。
打开的文件使用完成后一定要关闭,fstream 提供了成员函数 close()来完成此操作,如: fstream::open(file1);file1.close();就把 file1 相连的文件关闭。
读写文件分为文本文件和二进制文件的读取,对于文本文件的读取比较简单,用插入器和析 取器就可以了;而对于二进制的读取就要复杂些,下要就详细的介绍这两种方式 :
1、文本文件的读写 (ASCII)
文本文件的读写很简单:用插入器(<<)向文件输出,用析取器(>>)从文件输入。假设 file1 是以输入方式打开,file2 以输出打开。示如下:
这种方式还有一种简单的格式化能力,比如可以指定输出为 16 进制等等,具体的格式有以 下一些 :
比如要把 256当作十六进制输出:file1< 2、二进制文件的读写(binary) 1)put() put()函数向流写入一个字符,其原型是 ofstream &put(char ch),使用也比较简单,如 file1.put('c');就是向流写一个字符'c'。 2)get() get()函数比较灵活,有 3 种常用的重载形式: 一种就是和 put()对应的形式: ifstream &get(char &ch); 功能是从流中读取一个字符, 结果保存在引用 ch中,如果到文件尾,返回空字符。如 file2.get(x);表示从文件中读取一个字 符,并把读取的字符保存在 x 中。 另一种重载形式的原型是: int get(); 这种形式是从流中返回一个字符,如果到达文件尾, 返回 EOF,如 x=f ile2.get();和上例功能是一样的。 还有一种形式的原型是: ifstream &get(char *buf,int num,char delim='n') ; 这种形式把字符读入由 buf 指向的数组,直到读入了 num 个字符或遇到了由 delim 指定的字符, 如果没使用 delim 这个参数,将使用缺省值换行符'n'。例如: file2.get(str1,127,'A');//从文件中读取字符到字符串 str1,当遇到字符'A'或读取了 127 个字符时终止。 3)读写数据块 要读写二进制数据块,使用成员函数 read()和 write()成员函数,它们如下: 对于read()函数,buf 应当是一个字符数组,由文件读出的数据将被保存在这儿。对于write()函数,buf 是一个字符数组,它用以存放你要写入文件的数据。read()从文件中读取 num 个字符到 buf 指向的缓存中,如果在还未读入 num 个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际读取的字符数;而 write() 从 buf 指向的缓存写 num 个字符到文件中,值得注意的是缓存的类型是 unsigned char *,有时可能需要类型转换。 成员函数 eof()用来检测是否到达文件尾,如果到达文件尾返回非 0 值,否则返回 0。原型是 int eof(); 例:if(in.eof())printf("已经到达文件尾\n"); C++ I/O 系统管理两个与一个文件相联系的指针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写操作的位置。每次执行输入或输出时,相应的指针自动变化。所以,C++ 的文件定位分为读位置和写位置的定位,对应的成员函数是seekg()和 seekp(),seekg()是设置读位置,seekp 是设置写位置。它们最通用的形式如下: streamoff 定义于 iostream.h 中,定义有偏移量 offset 所能取得的最大值,seek_dir 表示移动的基准位置,是一个有以下值的枚举: 这两个函数一般用于二进制文件,因为文本文件会因为系统对字符的解释而可能与预想的值 不同。 【4】检测 EOF
【5】文件定位