C++文件操作

文件操作必须包含的头文件#include <fstream>
一、C++文件操作类型
ofstream:写入文件的操作类,从内存到硬盘(从ostream引申而来)
ifstream:读取文件的操作类,从硬盘到内存(从istrean引申而来)
fstream:可同时写入读取文件的操作类(从iostream引申而来)

二、打开文件
fstream类中,成员函数fopen()用于打开文件
void open(const char* filename, int mode, int access);
参数:
filename:要打开的文件名;mode:要打开文件的方式;access:打开文件的属性;
mode分类:
ios::app : 以追加的方式打开文件
ios::ate : 文件打开后定位到文件尾,ios:app就包含有此属性
ios::binary : 以二进制方式打开文件,缺省的方式是文本方式
ios::in : 文件以输入方式打开(文件数据输入到内存)
ios::out : 文件以输出方式打开(内存数据输出到文件)
ios::nocreate : 不建立文件,所以文件不存在时打开失败
ios::noreplace : 不覆盖文件,所以打开文件时如果文件存在失败
ios::turnc : 如果文件存在,把文件长度设为0
打开方式可以连接使用,如ios::out|ios::binary
打开文件的属性分类:
0 : 普通文件,打开访问
1 : 只读文件
2 : 隐含文件
4 : 系统文件
属性分类可以连接使用,如1|2

打开文件实例:
fstream ExampleFile1;
ExampleFile1.open("D:\\test.txt", ios::out|ios::binary, 0);

fstream,ifstream,ofstream得成员函数open()都包含一个默认打开方式,如下所示:
ofstream ios::out|ios::turnc
ifstream ios::in
fstream ios::in|ios::out

使用成员函数bool is_open();来检查文件是否已经打开,true为打开成功,false为打开失败。

关闭文件:
当文件读写操作完成之后,我们必须将文件关闭以使文件重新变为可访问的。关闭文件需要调用成员函数close(),它负责将缓存中的数据排放出来并关闭文件。它的格式很简单:
void close ();
这个函数一旦被调用,原先的流对象(stream object)就可以被用来打开其它的文件了,这个文件也就可以重新被其它的进程(process)所有访问了。
为防止流对象被销毁时还联系着打开的文件,析构函数(destructor)将会自动调用关闭函数close。

向文件test.txt中写入一些数据。
代码如下:
int main()
{
ofstream ExampleFile("test.txt");
if (ExampleFile.is_open())
{
ExampleFile << "This is a line.\n";
ExampleFile << "This is another line .";
ExampleFile.close();
}
else
cout << "error" << endl;
return 0;
}
执行结果如下:

从test.txt文件读取内容,并打印到屏幕上。
代码如下:
int main()
{
char szBuff[128];
ifstream ExampleRead("test.txt");
if (!ExampleRead.is_open())
{
cout << "Error opening file!" << endl;
exit(1);
}

while (!ExampleRead.eof())
{
ExampleRead.getline(szBuff, 30);
cout << szBuff << endl;
}
return 0;
}
执行结果如下:

三、状态标识符的验证
eof() : 是ifstream从类ios继承过来的,到达文件末尾时,返回true;
bad() : 读写过程中出错,返回true;如对一个不是打开为写状态的文件进行写入时,写入的设 备没有剩余空间的时候等。
fail() : 除了与bad() 同样的情况下会返回 true 以外,加上格式错误时也返回true ,例如当想要读入一个整数,而获得了一个字母的时候。
good() : 如果调用以上任何一个函数返回true 的话,此函数返回 false

获得和设置流指针(get and put stream pointers):
所有输入/输出流对象(i/o streams objects)都有至少一个流指针:
ifstream, 类似istream, 有一个被称为get pointer的指针,指向下一个将被读取的元素。
ofstream, 类似 ostream, 有一个指针 put pointer ,指向写入下一个元素的位置。
fstream, 类似 iostream, 同时继承了get 和 put

流指针位置操作:
tellg() : 返回pos_type 类型的值(根据ANSI-C++ 标准) ,就是一个整数,代表当前get 流指针的位置。
tellp() : 返回pos_type 类型的值(根据ANSI-C++ 标准) ,就是一个整数,代表当前put流指针的位置 。
seekg()、seekp() : 用来改变流指针get、put的位置。被重载为两种不同的原型:
seekg(pos_type position);
seekp(pos_type position);
流指针被改变为指向从文件开始计算的一个绝对位置。

seekg(off_type offset, seekdir direction);
seekp(off_type offset, seekdir direction);
指定由参数direction决定的一个具体指针开始计 算的一个位移。

参数offset类型:
与tellg()和tellp()的返回值类型相同。
参数direction类型:
ios::beg : 从流开始位置计算的位移
ios::cur : 从流指针当前位置开始计算的位移
ios::end : 从流末尾处开始计算的位移

注意:
流指针 get 和 put 的值对文本文件(text file)和二进制文件(binary file)的计算方法都是不同的,因为文本模式的文件中某些特殊字符可能被修改。由于这个原因,建议对以文本文件模式打开的文件总是使用seekg 和 seekp的第一种原型,而且不要对tellg 或 tellp 的返回值进行修改。对二进制文件,你可以任意使用这些函数,不会有任何意外的行为产生。

四、二进制文件操作
获取当前文件main.cpp的大小:
代码如下:
#include <iostream>
#include <fstream>
using namespace std;

void main()
{
const char* pFileName = "main.cpp";
ifstream ExampleRead(pFileName, ios::in|ios::binary);
if (!ExampleRead.is_open())
{
cout << "Error opening file. \n";
return;
}
long lBegin = 0, lEnd = 0;
lBegin = ExampleRead.tellg();
ExampleRead.seekg(0, ios::end);
lEnd = ExampleRead.tellg();
ExampleRead.close();
cout << "size of " << pFileName << "is " << (lEnd - lBegin) << " bytes.\n" << endl;
system("pause");
return;
}

执行结果如下:


write和read函数使用:
write和read是文件流为顺序读写数据特殊设计的成员函数。
write(char* buffer, streamsize size); // 继承ostream,顺序写
read(char* buffer, streamsize size); // 继承istream,顺序读

使用read()从test.txt文件中读取内容并显示到屏幕
代码如下:
void main()
{
const char* pFileName = "test.txt";
ifstream ExampleRead(pFileName, ios::in | ios::binary | ios::ate);
if (!ExampleRead.is_open())
{
cout << "Error opening file.\n";
exit(1);
}
long lSize = ExampleRead.tellg();
ExampleRead.seekg(0, ios::beg);
char* buffer;
buffer = new char[lSize + 1];
buffer[lSize] = '\0';
ExampleRead.read(buffer, lSize);
ExampleRead.close();
cout << (char*)buffer << endl;
delete[] buffer;
system("pause");
return;
}
执行结果如下:

五、缓存和同步机制
当我们对文件流进行操作的时候,它们与一个streambuf 类型的缓存(buffer)联系在一起。这个缓存(buffer)实际是一块内存空间,作为流(stream)和物理文件的媒介。例如,对于一个输出流, 每次成员函数put (写一个单个字符)被调用,这个字符不是直接被写入该输出流所对应的物理文件中的,而是首先被插入到该流的缓存(buffer)中。
当缓存被排放出来(flush)时,它里面的所有数据或者被写入物理媒质中(如果是一个输出流的话),或者简单的被抹掉(如果是一个输入流的话)。这个过程称为同步(synchronization),它会在以下任一情况下发生:
当文件被关闭时: 在文件被关闭之前,所有还没有被完全写出或读取的缓存都将被同步。
当缓存buffer 满时:缓存Buffers 有一定的空间限制。当缓存满时,它会被自动同步。
控制符明确指明:当遇到流中某些特定的控制符时,同步会发生。这些控制符包括:flush 和endl。

明确调用函数sync(): 调用成员函数sync() (无参数)可以引发立即同步。这个函数返回一个int 值,等于-1 表示流没有联系的缓存或操作失败
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章