C++學習手記六:C++文件處理 頂 原

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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章