一、概述
C中对文件的操作是通过 FILE文件指针 和相关关函数来实现的。
C++中是通过 fstream文件流 来实现的,其包含 ifstream、ofstream、fstream 三个类,通过定义这三个类的对象实现相对应的文件操作。
二、C中的文件操作
1、打开文件
包括 fopen()、freopen()、tmpfile() 三个函数,他们都会返回一个指向 FILE 对象的指针。该 FILE 对象包控制被打开文件相关联的流的所有信息,包括指向缓冲区的指针、文件位置指示器、指示错误和文件结尾情况的标志等。如果成功,该指针就指向已打开的流,如果失败,该指针就为空指针
打开文件后就可以调用相关函数对流进行处理。这些函数都把指向 FILE 对象的指针(FILE 指针)作为它们的参数之一。
FILE *fopen(const char * restrict filename, const char * restrict mode);
FILE *freopen(const char * restrict filename, const char * restrict mode, FILE * restrict stream);
FILE *tmpfile(void);
/*
* For example
*/
#include <stdio.h>
#include <stdbool.h>
_Bool isReadWriteable( const char *filename )
{
FILE *fp = fopen( filename, "r+" ); //打开一个文件以用于读写
if ( fp != NULL ) //fopen()是否执行成功
{
fclose(fp); //成功:关闭文件,没有错误需要处理
return true;
}else{
return false; // 失败
}
}
2、关闭文件
关闭文件时需要使用函数 fclose() 。关闭成功返回 0;异常返回 EOF,表示文件在关闭时发生错误。
int fclose( FILE *fp );
三、C++中的文件操作
C++中是通过 fstream 文件流(以及其成员函数)实现对文件的操作,头文件如下所示,其包含三个类:
- ifstream(代表输入文件,从硬盘到内存,支持 >> 操作符)
- ofstream(代表输出文件,从内存到硬盘,支持 << 操作符)
- fstream(代表输入输出文件,同时支持 >> 和 << 操作符)
#include <fstream> //头文件
ofstream //文件写操作,内存写入存储设备
ifstream //文件读操作,存储设备读取到内存中
fstream //读写操作,对打开的文件可进行读写操作
文件流的 常用成员函数 如下所示。从 bad() 函数开始为验证流状态的常用成员函数,返回值均为 bool 型。
- open(),打开文件
- close(),关闭文件
- read(),顺序读数据
- write(),顺序写数据
- is_open(),判断文件是否打开,打开则返回true
- bad(),如果在读写过程中出错,返回true
- fail(),除了与bad()同样的情况下返回true外;遇到格式错误时也返回true,例如当需要读入一个int ,而得到一个char
- eof(),如果读文件到达文件的末尾,返回true
- good(),最通用的验证,如果遇上以上任何一个函数返回true的话,此函数返回false
- clear(),重置以上成员函数所检查的状态标志,没有参数
1、打开文件——Open()函数
Open()函数如下,其中 filename 代表操作文件名、mode 代表打开方式、prot 代表打开文件属性
/*
* Open函数的定义
*/
void open(const char * filename,
ios_base::openmode mode = ios_base::in | ios_base::out);
void open(const wchar_t *_Filename, ios_base::openmode mode= ios_base::in | ios_base::out,
int prot = ios_base::_Openprot);
/* Mode的可选参数 */
ios::in 为输入(读)而打开文件
ios::out 为输出(写)而打开文件
ios::ate 初始位置:文件尾
ios::app 所有输出附加在文件末尾
ios::trunc 如果文件已存在先删除文件
ios::binary 二进制方式
/* Prot的可选参数 */
0 普通文件,打开文件
1 只读文件
2 隐含文件
3 系统文件
打开文件的方式可以单一使用,或者使用 '|' 组合使用
ofstream outfile;
outfile.open("Hello.txt", ios::in|ios::out|ios::binary);
若仅使用默认的打开方式可以不用显式的调用open()函数,直接使用流对象进行文件的操作。当使用默认的方式打开文件时,可以使用成员函数 is_open() 对文件进行是否已打开的验证。
ofstream out("\\\", ios::out);
ifstream in("\\\", ios::in);
fstream iofile("\\\", ios::in|ios::out);
2、关闭文件——Close()函数
Close()函数,对文件进行完读写操作之后,必须将文件关闭使得文件重新变成可以访问的。close()函数负责将缓存中的数据排放出来并关闭文件。
3、文本文件的读写
文本文件的读/写可以利用 << 和 >> 分别进行写和读
#include <fstream.h>
#include <iostream.h>
using namespace std;
int main() {...}
void func1(...) //文件的写操作
{
ofstream file("out.txt");
if(file.is_open())
{
fil e<< "This is a test" << endl;
file.close();
}
}
void func2(...) //文本的读入,并打印在屏幕上
{
char buff[520];
ifstream infile("in.txt");
if(!infile.is_open())
cout << "Error open" << endl;
while(!infile.eof())
{
infile.getline(buff, 100);
cout << buff << endl;
}
return 0;
}
通过 read()、write() 函数进行读写,它们是文件流为顺序读写数据特殊设计的成员函数。write是 ostream 的成员函数,read是 istream 的成员函数,类 fstream 的对象同时拥有这两个函数。
其原型如下, buffer 是一块用来存储或读出数据的内存地址,size 表示要从 buffer 中读出或写入的整数值。
write(char * buffer, streamsize size);
read(char * buffer, streamsize size);
4、获取和设置流指针
所有输入/输出流对象都有至少一个流指针:
- ifstream,类似istream,有一个被称为get pointer的指针,指向下一个将被读取的元素;
- ofsream,类似ostream,有一个被称为put pointer的指针,指向下一个元素的位置;
- fstream,类似iostream,同时继承了 get 和 put ;
读取/配置流指针的成员函数
- tellg() 和 tellp(),这两个函数不用传入参数,返回pos_type类型的值,即一个整数,代表当前get流指针的位置(用tellg)或put流指针的位置(用tellp)。
- seekg() 和 seekp(),这对函数分别用来改变指针get和put的位置。两个函数都被重载为两种不同的原型:
//使用这个原型,流指针被改变为指向从文件开始计算的一个绝对位置;
//要求传入的参数类型与函数 tellg 和tellp 的返回值类型相同。
seekg(pos_type position);
seekp(pos_type position);
//使用这个原型可以指定由参数direction决定的一个具体的指针开始计算的一个位移(offset)。
seekg(off_type offset, seekdir direction);
seekp(off_type offset, seekdir direction);
//direct的可选参数
//ios::beg 从流开始位置计算的位移
//ios::cur 从流指针当前位置开始计算的位移
//ios::end 从流末尾处开始计算的位移
需要注意的是,流指针 get 和 put 的值对文本文件(text file)和二进制文件(binary file)的计算方法都是不同的,因为文本文件中某些特殊字符可能被修改。因此,建议
- 对以文本文件模式打开的文件总是使用 seekg 和 seekp 的第一种原型,而且不要对tellg 或 tellp 的返回值进行修改;
- 对二进制文件,你可以任意使用这些函数,应该不会有任何意外的行为产生;
//获取二进制文件的大小
#include <iostream.h>
#include <fstream.h>
const char * filename = "test.txt";
int main()
{
long l,m;
ifstream in(filename, ios::in|ios::binary);
l = in.tellg();
in.seekg (0, ios::end);
m = in.tellg();
in.close();
cout << "size of " << filename;
cout << " is " << (m-l) << " bytes.\n";
return 0;
}