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