二進位檔案 I/O


使用二進位模式開啟檔案,在寫入或讀取檔案時不會發生字元轉換,數值在記憶體中的位元是如何,寫入檔案時就是如何,而讀入時也是相同。

下面這個程式可以讀入任意檔案,每次讀入一個位元組,並將讀入資料以 16 進位數顯示,若讀入的資料前導位元為 1,為了輸出的對齊,使用其補數加以顯示:

#include <iostream> 
#include <fstream> 
#include <iomanip> 
using namespace std; 

void print(ifstream &in) {
    char ch; 
    int count = 0;     
    while(!in.eof()) { 
        in.get(ch); 
        if(ch < 0) {
            ch = ~ch;     // 負數取補數 
        }
        cout << setw(2) << hex << static_cast<int>(ch) << " "; 
        count++; 
        if(count > 16) {  // 換行 
            cout << endl; 
            count = 0; 
        } 
    } 
    cout << endl; 
}

int main(int argc, char* argv[]) { 
    ifstream in(argv[1], ios::in | ios::binary); 
    if(!in) { 
        cout << "無法讀取檔案" << endl; 
        return 1; 
    } 

    print(in);
    in.close(); 

    return 0; 
}

執行結果:

23 69 6e 63 6c 75 64 65 20 3c 69 6f 73 74 72 65 61
6d 3e  a 23 69 6e 63 6c 75 64 65 20 3c 66 73 74 72
65 61 6d 3e  a 23 69 6e 63 6c 75 64 65 20 3c 69 6f
6d 61 6e 69 70 3e  a 75 73 69 6e 67 20 6e 61 6d 65
73 70 61 63 65 20 73 74 64 3b  a  a 69 6e 74 20 6d
61 69 6e 28 69 6e 74 20 61 72 67 63 2c 20 63 68 61
略....

下面這個程式可以讓將檔案複製至另一指定名稱:

#include <iostream> 
#include <fstream> 
using namespace std; 

int main(int argc, char* argv[]) { 
    char ch; 

    ifstream in(argv[1], ios::in | ios::binary); 
    ofstream out(argv[2], ios::out | ios::binary); 

    while(!in.eof()) { 
        in.get(ch); 
        if(!in.eof()) 
            out.put(ch); 
    } 

    in.close(); 
    out.close(); 

    return 0;
}

在寫入或讀取檔案時,也可以用 readwrite 函式以區塊的方式寫入,它們的函式雛型如下:

istream &read(char *buf, streamsize num);
ostream &write(const char* buf, streamsize num);

其中 num 是要寫入的資料位元組數目,下面這個程式示範如何將陣列資料寫入檔案,然後再將之讀出:

#include <iostream> 
#include <fstream> 
using namespace std; 

int main(int argc, char* argv[]) { 
    ofstream out("temp", ios::out | ios::binary); 
    int arr[5] = {1, 2, 3, 4, 5}; 
    out.write(reinterpret_cast<char*>(arr), sizeof(arr)); 
    out.close(); 

    ifstream fin("temp", ios::in | ios::binary); 
    fin.read(reinterpret_cast<char*>(arr), sizeof(arr)); 
    for(int i = 0; i < 5; i++) {
        cout << arr[i] << ' '; 
    }
    cout << endl; 
    fin.close(); 

    return 0; 
}