C++文件操作的常见头文件分别为<iostream>和<fstream>
本文规定输入流(stream input)的方向是从文件到程序的流,输出流为程序到文件的流。
顺序存取文件读写:
向硬盘中写入文件示例(C++11 Chap 14.3 p.g.447):
// Fig. 14.3: fig14_03.cpp
// Create a sequential file.
#include <iostream>
#include <string>
#include <fstream> // contains file stream processing types
#include <cstdlib> // exit function prototype
using namespace std;
int main()
{
// ofstream constructor opens file
ofstream outClientFile("../Read_From_File/clients.txt", ios::out);
//Can also be written as this because ios::out is by default:
//ofstream outClientFile( "../Read_From_File/clients.txt" );
// //Can also be written as:
// ofstream outClientFile;
// outClientFile.open("../Read_From_File/clients.txt");
// exit program if unable to create file
if ( !outClientFile ) // overloaded ! operator
{
cerr << "File could not be opened" << endl;
exit( EXIT_FAILURE );
} // end if
cout << "Enter the account, name, and balance." << endl
<< "Enter end-of-file to end input.\n? ";
int account; // the account number
string name; // the account owner's name
double balance; // the account balance
// read account, name and balance from cin, then place in file
while ( cin >> account >> name >> balance )
{
outClientFile << account << ' ' << name << ' ' << balance << endl;
cout << "? ";
} // end while
outClientFile.close();
} // end main
一般地,C++文件有以下几种打开方式:
- ios::app,打开文件,并使得输出流从文件结尾位置开始输出
- ios::ate,打开文件,并指向文件结尾(通常也是用于扩展文件)
- ios::in,打开文件,启用输入流
- ios::out,若文件已经存在,打开并清空文件;若文件不存在,新建文件。启用输出流写数据
- ios::trunc,清空原文件中的内容
- ios::binary,以二进制形式打开文件,准备读写二进制流
在程序中读取硬盘文件示例:
// Fig. 14.6: fig14_06.cpp
// Reading and printing a sequential file.
#include <iostream>
#include <fstream> // file stream
#include <iomanip>
#include <string>
#include <cstdlib> // exit function prototype
using namespace std;
void outputLine( int, const string &, double ); // prototype
int main()
{
// ifstream constructor opens the file
ifstream inClientFile( "clients.txt", ios::in );
// exit program if ifstream could not open file
if ( !inClientFile )
{
cerr << "File could not be opened" << endl;
exit( EXIT_FAILURE );
} // end if
int account; // the account number
string name; // the account owner's name
double balance; // the account balance
cout << left << setw( 10 ) << "Account" << setw( 13 )
<< "Name" << "Balance" << endl << fixed << showpoint;
// display each record in file
while ( inClientFile >> account >> name >> balance )
outputLine( account, name, balance );
} // end main
// display single record from file
void outputLine( int account, const string &name, double balance )
{
cout << left << setw( 10 ) << account << setw( 13 ) << name
<< setw( 7 ) << setprecision( 2 ) << right << balance << endl;
} // end function outputLine
在顺序存取文件中,光标所指的字符位置可以通过seekg(对于输入流来说)以及seekp(对于输出流来说)进行更改,可以通过tellp和tellg获得。这两个函数的使用示例如下(C++11 Chap 14.4 p.g.452):
//光标指向文件的第n字节,默认模式ios::beg
fileObj.seekg(n); 或
//fileObj.seekg(n, ios::beg);
//由于ios::beg为默认模式,因此可以不指定
//光标指向文件从当前位置往后算n字节:
fileObj.seekg(n, ios::cur);
//光标指向文件结尾往回算第n字节:
fileObj.seekg(n, ios::end);
//获取光标当前位置:
long location = fileObj.tellg();
fileObj.clear()往往与fileObj.seekp(n)配合使用,用于清除当前光标状态并重新寻找文件中相应的位置。
在I/O操作中,remove(char * path)函数(头文件<stdio.h>)用于删除已存在的文件,但需要注意删除之前必须先关闭文件。
随机存取文件读写
随机存取文件是指文件中任何内容的搜索成本都是O(1)的文件。随机存取文件往往以对象的形式存储整块内容,由于每块内容大小相同,因此通过寻找相应的块号码则可以快速读取文件内容。由于大量的块事实上可能是空块,因此随机存取策略是一个典型的用空间换时间的流存取策略(C++11 Chap 14.9 p.g.466)
随机存取文件初始化示例如下:
ofstream outCredit( “credit.dat”, ios::out | ios::in | ios::binary);
//If can not open, generate error information, similar as examples above:
if(!outCredit){...}
//Suppose ClientData is an already defined class
ClientData blankClient;
for(int i = 0; i < 100; i++)
outCredit.write( reinterpret_cast<const char *>( &blankClient), sizeof(ClientData) );
写入/更新示例如下:
// seek position in file of user-specified record
outCredit.seekp( ( client.getAccountNumber() - 1 ) *
sizeof( ClientData ) );
// write user-specified information in file
outCredit.write( reinterpret_cast<char *>(&client),
sizeof( ClientData ) );
读取示例如下:
//Prototype of output function:
void outputLine( ostream&, const ClientData & );
//in main:
ifstream inCredit( "../RandomAccessProject/credit.txt", ios::in | ios::binary );
// read all records from file
while ( inCredit && !inCredit.eof() )
{
// display record
if ( client.getAccountNumber() != 0 )
outputLine( cout, client );
// read next from file
inCredit.read( reinterpret_cast< char * >( &client ),
sizeof( ClientData ) );
} // end while