C++中的檔案操作

hisun9發表於2024-10-18

使用C++標準庫進行檔案操作

1. 概述

C++標準庫提供了 <fstream> 標頭檔案中的幾個類來進行檔案操作,這些類封裝了底層的檔案操作,提供了物件導向和型別安全的介面,使得檔案讀寫更加便捷和高效。主要的檔案流類包括:

std::ifstream:用於從檔案中讀取資料。

std::ofstream:用於向檔案中寫入資料。

std::fstream:用於同時讀取和寫入檔案。

這些檔案流類(std::ifstream、std::ofstream、std::fstream)繼承自 std::istream、std::ostream 和 std::iostream,這些類本身繼承自 std::ios,從而提供了豐富的成員函式和運算子來處理檔案I/O。

更詳細的關於繼承關係的介紹:C++標準庫中檔案流類的繼承關係

2. 檔案流類詳解

2.1 std::ifstream:輸入檔案流

std::ifstream 用於從檔案中讀取資料。它繼承自 std::istream,具備所有輸入流的功能,同時新增了檔案特有的操作。

例子:

#include <fstream>
#include <iostream>
#include <string>

int main() {
    // 建立並開啟輸入檔案流
    std::ifstream infile("input.txt"); // "input.txt" 是要讀取的檔名

    // 檢查檔案是否成功開啟
    if (!infile) {
        std::cerr << "無法開啟檔案 input.txt" << std::endl;
        return 1;
    }

    // 讀取並輸出檔案內容
    std::string line;
    while (std::getline(infile, line)) {
        std::cout << line << std::endl;
    }

    // 關閉檔案流(可選,因為解構函式會自動關閉)
    infile.close();

    return 0;
}

要點:

  • 建構函式可以在建立物件時指定檔名和開啟模式。

  • 檢查檔案是否成功開啟,以避免後續操作錯誤。

  • 使用 std::getline 逐行讀取檔案內容。

補充:

std::ifstream infile("input.txt");的解釋:

  1. std::ifstream

    定義:std::ifstream 是 C++ 標準庫中用於輸入檔案流的類,定義在 <fstream> 標頭檔案中。

    用途:用於從檔案中讀取資料。ifstream 代表“輸入檔案流”(input file stream)。

    繼承關係:std::ifstream 繼承自 std::istream,而 std::istream 又繼承自 std::ios,提供了豐富的成員函式和運算子來處理檔案輸入操作。

  2. infile

    定義:infile 是一個變數名,是 std::ifstream 類的一個物件例項。在這裡,infile 可以被認為是一個檔案讀取流,用於從指定的檔案中讀取資料。

    作用:透過 infile,你可以執行各種讀取操作,例如讀取單詞、行、整個檔案內容,甚至是二進位制資料。

  3. 建構函式 std::ifstream infile("input.txt")

    功能:這行程式碼做了兩件事:

    • 建立物件:宣告並建立了一個 std::ifstream 物件,名為 infile。

    • 開啟檔案:在建立物件的同時,透過建構函式引數 "input.txt" 指定要開啟的檔名。預設情況下,std::ifstream 會以只讀模式開啟檔案。

    過程:

    • 當 infile 物件被建立時,std::ifstream 的建構函式會嘗試開啟 "input.txt" 檔案。

    • 如果檔案成功開啟,infile 就可以用於後續的讀取操作。

    • 如果檔案無法開啟(例如檔案不存在或許可權不足),infile 的狀態會被設定為失敗,你可以透過檢查流的狀態來處理這種情況。

  4. infile 的靈活性

    • 讀取不同型別的資料:

      你可以使用不同的方法和運算子來讀取檔案內容。例如,使用 >> 運算子從檔案中讀取單詞,或者使用 read() 方法讀取二進位制資料。

    • 錯誤處理:

      除了檢查檔案是否成功開啟,還可以檢查讀取操作是否成功,例如使用 infile.good(), infile.eof(), infile.fail() 等成員函式。

    • 多種開啟模式:

      std::ifstream 還支援多種開啟模式,透過建構函式的第二個引數指定。例如,以二進位制模式開啟檔案:

      std::ifstream infile("input.bin", std::ios::binary);
      

2.2 std::ofstream:輸出檔案流

std::ofstream 用於向檔案中寫入資料。它繼承自 std::ostream,具備所有輸出流的功能,同時新增了檔案特有的操作。

例子:

#include <fstream>
#include <iostream>
#include <string>

int main() {
    // 建立並開啟輸出檔案流
    std::ofstream outfile("output.txt"); // "output.txt" 是要寫入的檔名

    // 檢查檔案是否成功開啟
    if (!outfile) {
        std::cerr << "無法開啟檔案 output.txt" << std::endl;
        return 1;
    }

    // 寫入資料到檔案
    outfile << "Hello, World!" << std::endl;
    outfile << "這是第二行文字。" << std::endl;

    // 關閉檔案流(可選,因為解構函式會自動關閉)
    outfile.close();

    return 0;
}

要點:

  • 預設情況下,std::ofstream 以寫入模式開啟檔案。如果檔案不存在,會建立新檔案;如果檔案存在,會截斷檔案內容。

  • 使用 << 運算子向檔案中插入資料。

2.3 std::fstream:檔案流(讀寫)

std::fstream 用於同時讀取和寫入檔案。它繼承自 std::iostream,結合了 std::istream 和 std::ostream 的功能

例子:

#include <fstream>
#include <iostream>
#include <string>

int main() {
    // 建立並開啟檔案流,設定為讀寫模式
    std::fstream file("file.txt", std::ios::in | std::ios::out | std::ios::app);

    // 檢查檔案是否成功開啟
    if (!file) {
        std::cerr << "無法開啟檔案 file.txt" << std::endl;
        return 1;
    }

    // 寫入資料到檔案
    file << "追加一行內容。" << std::endl;

    // 移動讀指標到檔案開頭
    file.seekg(0, std::ios::beg);

    // 讀取並輸出檔案內容
    std::string line;
    while (std::getline(file, line)) {
        std::cout << line << std::endl;
    }

    // 關閉檔案流
    file.close();

    return 0;
}

要點:

  • 透過建構函式的第二個引數指定檔案開啟模式,可以組合多個模式。

  • 適用於需要同時進行讀取和寫入操作的場景。

3. 開啟和關閉檔案

檔案流類提供了多種方式來開啟和關閉檔案。

使用建構函式開啟檔案

可以在建立檔案流物件時,透過建構函式直接指定檔名和開啟模式。

比如:

std::ifstream infile("input.txt"); // 以預設模式(即只讀方式)開啟 input.txt
std::ofstream outfile("output.txt", std::ios::out | std::ios::trunc); // 以寫入和截斷模式開啟 output.txt

使用 open() 成員函式

如果在建立物件時沒有指定檔名,可以使用 open() 成員函式在後續開啟檔案。

比如:

#include <fstream>
#include <iostream>

int main() {
    std::ifstream infile; // 建立輸入檔案流物件
    infile.open("input.txt"); // 開啟檔案

    if (!infile.is_open()) {
        std::cerr << "無法開啟檔案 input.txt" << std::endl;
        return 1;
    }

    // 進行讀取操作...

    infile.close(); // 關閉檔案

    return 0;
}

關閉檔案

使用 close() 成員函式可以顯式關閉檔案流。儘管在物件銷燬時,解構函式會自動關閉檔案,但在需要提前釋放資源時,顯式呼叫 close() 是有用
的。

比如:

infile.close();
outfile.close();

4. 檔案開啟模式

檔案開啟模式透過 std::ios::openmode 列舉型別指定,可以組合使用多個模式。

常用的開啟模式:

  • std::ios::in:以讀取模式開啟檔案。

  • std::ios::out:以寫入模式開啟檔案。

  • std::ios::app:以追加模式開啟檔案,寫入操作將新增到檔案末尾。

  • std::ios::ate:開啟檔案後,將檔案指標定位到檔案末尾。

  • std::ios::trunc:如果檔案已存在,則截斷檔案長度為0(預設與 std::ofstream 相關)。

  • std::ios::binary:以二進位制模式開啟檔案。

比如:

// 以讀寫模式開啟檔案,不截斷現有內容
std::fstream file("data.txt", std::ios::in | std::ios::out);

// 以二進位制模式寫入資料, 截斷現有檔案內容

std::ofstream binaryOut("data.bin", std::ios::out | std::ios::binary | std::ios::trunc);

說明:

  • 組合使用:透過按位或運算子 | 組合多個開啟模式,如 std::ios::in | std::ios::out 表示同時具備讀取和寫入許可權。

  • 二進位制模式:對於非文字檔案(如圖片、音訊等),應使用 std::ios::binary 模式,以防止資料在讀取或寫入過程中被轉換。

5. 讀取檔案

5.1 使用 >> 運算子讀取單詞

>> 運算子用於從檔案中提取資料,自動跳過空白字元(如空格、換行符、製表符)。

比如:

假設 words.txt 檔案內容如下:

img

執行以下程式:

#include <fstream>
#include <iostream>
#include <string>

int main() {
    std::ifstream infile("words.txt");

    if (!infile) {
        std::cerr << "無法開啟檔案 words.txt" << std::endl;
        return 1;
    }

    std::string word;
    while (infile >> word) { // 逐詞讀取
        std::cout << "讀取到的單詞: " << word << std::endl;
    }

    infile.close();
    return 0;
}

輸出如下:

img

說明:

  • 適用於逐詞讀取資料,適合處理由空白字元分隔的資料。

  • 無法讀取包含空格的完整句子或短語。

5.2 使用 std::getline 逐行讀取

std::getline 函式用於從檔案中逐行讀取資料,適用於處理文字檔案中的行資料。

比如:

假設 lines.txt 檔案內容如下:

img

執行以下程式碼:

#include <fstream>
#include <iostream>
#include <string>

int main() {
    std::ifstream infile("lines.txt");

    if (!infile) {
        std::cerr << "無法開啟檔案 lines.txt" << std::endl;
        return 1;
    }

    std::string line;
    while (std::getline(infile, line)) { // 逐行讀取
        std::cout << "讀取到的行: " << line << std::endl;
    }

    infile.close();
    return 0;
}

輸出如下:

img

說明:

  • 適用於逐行處理檔案內容,保留每行的完整資訊。

  • 可以處理包含空格和其他特殊字元的行。

5.3 讀取整個檔案內容

有時需要一次性讀取整個檔案內容,尤其適用於小檔案或需要對整個檔案內容進行處理的場景。

比如:

假設 content.txt 檔案內容如下:

img

執行以下程式碼:

#include <fstream>
#include <iostream>
#include <string>

int main() {
    std::ifstream infile("content.txt");

    if (!infile) {
        std::cerr << "無法開啟檔案 content.txt" << std::endl;
        return 1;
    }

    // 使用迭代器讀取整個檔案內容到字串
    std::string content((std::istreambuf_iterator<char>(infile)),
                        std::istreambuf_iterator<char>());

    std::cout << "檔案內容:\n" << content << std::endl;

    infile.close();
    return 0;
}

輸出如下:

img

說明:

  • 使用 std::istreambuf_iterator 迭代器可以高效地讀取整個檔案內容。

  • 適用於小至中等大小的檔案,對於非常大的檔案,可能需要分塊讀取以避免記憶體問題。

  • 對此行程式碼的理解:

    std::string content((std::istreambuf_iterator<char>(infile)),
                        std::istreambuf_iterator<char>());
    
    • 這行程式碼使用了 std::istreambuf_iterator 來從輸入檔案流 infile 讀取內容並構建一個 std::string 物件。具體理解如下:

    • std::istreambuf_iterator(infile):建立一個輸入迭代器,從 infile 的緩衝區讀取字元。

    • std::istreambuf_iterator():這是一個空的迭代器,用於表示輸入結束。
      構造 std::string:透過傳入兩個迭代器,建構函式會從 infile 中讀取所有字元,直到遇到結束迭代器。

    • 最終,這行程式碼的作用是將整個檔案的內容讀入到 content 字串中。這樣,你就可以方便地對檔案內容進行操作。

5.4 讀取二進位制資料

對於非文字檔案(如圖片、音訊、影片等),需要以二進位制模式讀取資料,以防止資料在讀取過程中被轉換或丟失。

比如:

假設需要讀取一個圖片檔案 image.jpg 並輸出其大小。

img

執行以下程式碼:

#include <fstream>
#include <iostream>
#include <vector>

int main() {
    // 以二進位制模式開啟檔案
    std::ifstream infile("image.jpg", std::ios::binary);

    if (!infile) {
        std::cerr << "無法開啟檔案 image.jpg" << std::endl;
        return 1;
    }

    // 移動讀指標到檔案末尾以獲取檔案大小
    infile.seekg(0, std::ios::end);
    std::streamsize size = infile.tellg();
    infile.seekg(0, std::ios::beg);

    // 讀取檔案內容到緩衝區
    std::vector<char> buffer(size);
    if (infile.read(buffer.data(), size)) {
        std::cout << "成功讀取 " << size << " 位元組。" << std::endl;
    } else {
        std::cerr << "讀取檔案失敗!" << std::endl;
    }

    infile.close();
    return 0;
}

輸出如下:

img

說明:

  • 使用 std::ios::binary 模式開啟檔案,確保資料按原樣讀取。

  • 透過 seekg 和 tellg 獲取檔案大小,預分配緩衝區。

  • 使用 read 函式讀取二進位制資料到緩衝區。

  • 對這段程式碼的理解:

    infile.seekg(0, std::ios::end);
    std::streamsize size = infile.tellg();
    infile.seekg(0, std::ios::beg);
    

    這段程式碼用於確定並重置檔案流 infile 的位置,具體含義如下:

    • infile.seekg(0, std::ios::end);

      這行程式碼將檔案指標移動到檔案的末尾。seekg 函式用於設定輸入流的位置,0 是偏移量,std::ios::end 指定從檔案的末尾開始偏移。因此,檔案指標現在位於檔案末尾。

    • std::streamsize size = infile.tellg();

      tellg 函式返回當前檔案指標的位置(即檔案的長度)。因為我們剛剛將指標移動到了檔案末尾,size 將包含檔案的位元組數。

    • infile.seekg(0, std::ios::beg);

      這行程式碼將檔案指標重置迴檔案的開頭。std::ios::beg 指定從檔案的開頭開始偏移,因此現在指標又回到了檔案的起始位置。

    總結:這段程式碼的主要目的是獲取檔案的大小,並在讀取檔案內容之前重置檔案指標,以便可以從頭開始讀取資料。

6. 寫入檔案

6.1 使用 << 運算子寫入資料

<< 運算子用於向檔案中插入資料,類似於向標準輸出流 std::cout 中插入資料。

比如:

將使用者資訊寫入檔案 users.txt。

執行以下程式碼:

#include <fstream>
#include <iostream>
#include <string>

int main() {
    std::ofstream outfile("users.txt");

    if (!outfile) {
        std::cerr << "無法開啟檔案 users.txt" << std::endl;
        return 1;
    }

    // 寫入使用者資訊
    outfile << "使用者名稱: Alice\n年齡: 30\n" << std::endl;
    outfile << "使用者名稱: Bob\n年齡: 25\n" << std::endl;
    outfile << "使用者名稱: Charlie\n年齡: 35\n" << std::endl;

    outfile.close();

    std::cout << "使用者資訊已寫入 users.txt" << std::endl;
    return 0;
}

輸出如下:

img

未執行前,目錄如下:

img

執行後,目錄如下:

img

自動建立了個 users.txt 檔案,內容如下:

img

說明:

  • 使用 << 運算子可以方便地將各種資料型別寫入檔案。

  • std::endl 用於插入換行符並重新整理緩衝區。

6.2 使用 std::ofstream::write 寫入二進位制資料

對於需要寫入二進位制資料的場景,使用 write() 成員函式更為合適。

比如:

將一個字元陣列寫入二進位制檔案 output.bin。

執行以下程式碼:

#include <fstream>
#include <iostream>
#include <vector>

int main() {
    std::ofstream outfile("output.bin", std::ios::binary | std::ios::trunc);

    if (!outfile) {
        std::cerr << "無法開啟檔案 output.bin" << std::endl;
        return 1;
    }

    // 準備二進位制資料
    std::vector<char> data = {'H', 'e', 'l', 'l', 'o', '\0'};

    // 寫入二進位制資料到檔案
    outfile.write(data.data(), data.size());

    if (!outfile) {
        std::cerr << "寫入檔案失敗!" << std::endl;
    } else {
        std::cout << "成功寫入 " << data.size() << " 位元組到 output.bin" << std::endl;
    }

    outfile.close();
    return 0;
}

輸出如下:

img

同理,在目錄處也自動建立了一個 output.bin 檔案,內容如下:

img

說明:

  • 使用 write() 可以指定要寫入的資料地址和位元組數,適用於二進位制資料。

  • 確保檔案以二進位制模式開啟,防止資料被意外轉換。

  • outfile.write(data.data(), data.size());這行程式碼的理解:

    這行程式碼用於將資料寫入輸出檔案流 outfile,具體含義如下:

    • data.data():獲取 data 字串的指標,指向字串的首字元。這是寫入的起始地址。

    • data.size():返回字串 data 的長度,表示要寫入的位元組數。

    • outfile.write(data.data(), data.size());:呼叫 write 函式,將從 data 指標開始的 data.size() 位元組寫入 outfile 中。

    總體而言,這行程式碼的作用是將 data 字串的內容寫入到 outfile 檔案中。

7. 錯誤處理

檔案操作過程中可能會遇到各種錯誤,如檔案不存在、許可權不足、磁碟滿等。因此,進行適當的錯誤處理至關重要。

7.1 檢查檔案是否成功開啟

每次開啟檔案後,都應該檢查檔案流物件的狀態,以確保檔案成功開啟。

比如:

#include <fstream>
#include <iostream>

int main() {
    std::ifstream infile("nonexistent.txt");

    if (!infile.is_open()) { // 或者使用 !infile
        std::cerr << "無法開啟檔案 nonexistent.txt" << std::endl;
        return 1;
    }

    // 進行讀取操作...

    infile.close();
    return 0;
}

說明:

  • 使用 is_open() 成員函式檢查檔案是否成功開啟。

  • 也可以直接檢查流物件的狀態,如 if (!infile)

7.2 使用異常處理

C++檔案流可以配置為在發生錯誤時丟擲異常,提供更靈活的錯誤處理機制。

比如:

使用異常處理機制讀取檔案內容。

#include <fstream>
#include <iostream>
#include <string>

int main() {
    std::ifstream infile;

    // 設定檔案流在 failbit 或 badbit 時丟擲異常
    infile.exceptions(std::ifstream::failbit | std::ifstream::badbit);

    try {
        infile.open("data.txt");

        std::string line;
        while (std::getline(infile, line)) {
            std::cout << line << std::endl;
        }

        infile.close();
    } catch (const std::ifstream::failure& e) {
        std::cerr << "檔案操作異常: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}

輸出如下(因為沒有建立data.txt檔案,所以丟擲異常):

img

說明:

  • 使用 exceptions() 成員函式設定檔案流在特定錯誤狀態下丟擲異常。

  • 捕獲 std::ifstream::failure 異常,進行錯誤處理。

  • 預設情況下,檔案流不會丟擲異常,需顯式啟用。

  • 對這段程式碼的解釋:

    • std::ifstream infile;:宣告一個輸入檔案流物件 infile,用於讀取檔案。

    • infile.exceptions(std::ifstream::failbit | std::ifstream::badbit);

      設定檔案流在發生失敗(failbit)或嚴重錯誤(badbit)時丟擲異常,這樣可以透過 try-catch 機制來捕獲錯誤。

    • try {:開始一個異常處理塊,嘗試執行可能丟擲異常的程式碼。

    • infile.open("data.txt");:開啟名為 data.txt 的檔案進行讀取。如果檔案無法開啟,將丟擲異常。

    • std::string line;:宣告一個字串變數 line,用於儲存從檔案中讀取的每一行。

    • while (std::getline(infile, line)) {

      使用 getline 函式從 infile 中逐行讀取資料,直到檔案結束。每讀取一行,將其儲存在 line 中。

    • std::cout << line << std::endl;:將讀取的每一行輸出到控制檯。

    • infile.close();:關閉檔案流,釋放資源。

    • } catch (const std::ifstream::failure& e) {

      捕獲檔案流的異常,處理檔案操作錯誤。

    • std::cerr << "檔案操作異常: " << e.what() << std::endl;

      輸出錯誤資訊到標準錯誤流,e.what() 提供具體的錯誤描述。

    • return 1;:如果發生異常,返回 1 表示程式異常結束。

    • return 0;:正常結束程式,返回 0。

8. 高階主題

8.1 檔案指標位置控制

檔案流物件維護了讀寫指標的位置,可以透過成員函式 seekg()(用於輸入流)和 seekp()(用於輸出流)來移動指標。

比如:

讀取檔案中指定位置的資料。

假設 data.txt 的文字檔案,內容如下:

img

執行以下程式碼:

#include <fstream>
#include <iostream>
#include <string>

int main() {
    std::ifstream infile("data.txt", std::ios::binary);

    if (!infile) {
        std::cerr << "無法開啟檔案 data.txt" << std::endl;
        return 1;
    }

    // 獲取檔案大小
    infile.seekg(0, std::ios::end);
    std::streampos size = infile.tellg();
    std::cout << "檔案大小: " << size << " 位元組" << std::endl;

    // 移動指標到檔案中間位置
    std::streampos mid = size / 2;
    infile.seekg(mid, std::ios::beg);
    std::cout << "移動到檔案中間位置: " << mid << std::endl;

    // 讀取接下來的10個位元組
    char buffer[11] = {0}; // 10個字元 + 1個終止符
    infile.read(buffer, 10);
    std::cout << "讀取的資料: " << buffer << std::endl;

    infile.close();
    return 0;
}

輸出如下:

img

說明:

  • 使用 seekg() 移動讀指標位置。

  • 使用 tellg() 獲取當前讀指標的位置。

  • 適用於需要隨機訪問檔案內容的場景。

8.2 緩衝管理

檔案流物件使用緩衝區來提高I/O效率。可以使用 flush() 成員函式來強制將緩衝區的資料寫入檔案。

比如:

在寫入資料後立即重新整理緩衝區。

#include <fstream>
#include <iostream>
#include <string>

int main() {
    std::ofstream outfile("buffered_output.txt");

    if (!outfile) {
        std::cerr << "無法開啟檔案 buffered_output.txt" << std::endl;
        return 1;
    }

    outfile << "這是一行資料。";
    outfile.flush(); // 強制重新整理緩衝區

    outfile << "這是另一行資料。\n";

    outfile.close();
    return 0;
}

自動建立了buffered_output.txt檔案,內容如下:

img

9. 舉幾個例子

為了更好地理解如何綜合運用上述知識,以下提供幾個完整的示例,涵蓋讀取、寫入、錯誤處理和二進位制資料操作。

9.1 讀取文字檔案並處理資料

任務: 從 students.txt 檔案中讀取學生資訊,並輸出到控制檯。

假設 students.txt 內容如下:

img

執行以下程式碼:

#include <fstream>
#include <iostream>
#include <string>

int main() {
    std::ifstream infile("students.txt");

    if (!infile) {
        std::cerr << "無法開啟檔案 students.txt" << std::endl;
        return 1;
    }

    std::string name;
    int age;
    while (infile >> name >> age) {
        std::cout << "學生姓名: " << name << ", 年齡: " << age << std::endl;
    }

    if (infile.bad()) {
        std::cerr << "讀取檔案時發生嚴重錯誤!" << std::endl;
    } else if (infile.eof()) {
        std::cout << "已到達檔案末尾。" << std::endl;
    } else if (infile.fail()) {
        std::cerr << "讀取檔案時發生格式錯誤!" << std::endl;
    }

    infile.close();
    return 0;
}

輸出如下:

img

說明:

  • 使用 >> 運算子逐個讀取學生姓名和年齡。

  • 透過檢查 bad()eof()fail() 來處理不同型別的錯誤。

9.2 寫入文字檔案

任務: 將多個產品資訊寫入 products.txt 檔案。

執行以下程式碼:

#include <fstream>
#include <iostream>
#include <string>

int main() {
    std::ofstream outfile("products.txt");

    if (!outfile) {
        std::cerr << "無法開啟檔案 products.txt" << std::endl;
        return 1;
    }

    // 寫入產品資訊
    outfile << "產品名稱: 手機\n價格: 5000元\n\n";
    outfile << "產品名稱: 膝上型電腦\n價格: 8000元\n\n";
    outfile << "產品名稱: 電子書閱讀器\n價格: 1200元\n\n";

    outfile.close();

    std::cout << "產品資訊已寫入 products.txt" << std::endl;
    return 0;
}

輸出如下:

img

自動建立的products.txt檔案,內容如下:

img

說明:

  • 使用 << 運算子將字串和數值寫入檔案。

  • 透過插入 \n 實現換行和段落分隔。

9.3 複製二進位制檔案

任務: 複製一個二進位制檔案 source.jpg 到 destination.jpg。

假設 source.jpg 內容如下:

img

執行以下程式碼:

#include <fstream>
#include <iostream>

int main() {
    std::ifstream src("source.jpg", std::ios::binary);
    if (!src) {
        std::cerr << "無法開啟原始檔 source.jpg" << std::endl;
        return 1;
    }

    std::ofstream dest("destination.jpg", std::ios::binary | std::ios::trunc);
    if (!dest) {
        std::cerr << "無法建立目標檔案 destination.jpg" << std::endl;
        return 1;
    }

    // 複製檔案內容
    dest << src.rdbuf();

    if (!dest) {
        std::cerr << "複製檔案失敗!" << std::endl;
        return 1;
    } else {
        std::cout << "檔案複製成功。" << std::endl;
    }

    src.close();
    dest.close();
    return 0;
}

輸出如下:

img

自動建立了destination.jpg檔案,內容如下:

img

說明:

  • 使用 rdbuf() 將原始檔流的緩衝區內容直接傳輸到目標檔案流。

  • 適用於高效複製檔案內容,尤其是大檔案。

相關文章