首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

C++ iostream 定位操作完全指南:seekg/seekp/tellg/tellp 實戰

     編輯:C++ 入門

兩種定位模型

iostream 提供雙重定位機制,對應 C 標準庫 fseek/ftell:

  1. 絕對定位:streampos pos = tellg(); ... seekg(pos);
  2. 相對定位:seekg(offset, dir),dir 為 ios::beg/cur/end

核心函式對照表

操作輸入流 (istream)輸出流 (ostream)
取得當前位置tellg()tellp()
絕對定位seekg(pos)seekp(pos)
相對定位seekg(off, dir)seekp(off, dir)

streampos 通常為 std::fpos<mbstate_t>,可隱式轉換整數型別。

方向常數

std::ios::beg  // 檔案開頭
std::ios::cur  // 當前位置
std::ios::end  // 檔案結尾

完整範例:檔案大小與尾部讀取

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

int main() {
    std::ifstream in("Seeking.cpp", std::ios::binary);  // 二進位模式避免換行符轉換
    if (!in) return 1;

    // 1. 移至檔案尾,取得大小
    in.seekg(0, std::ios::end);
    std::streampos file_size = in.tellg();
    std::cout << "File size: " << file_size << " bytes\n";

    // 2. 從尾部倒數 1/10 處開始讀取
    in.seekg(-file_size / 10, std::ios::end);
    std::streampos start_pos = in.tellg();

    // 3. 印出完整檔案
    in.seekg(0, std::ios::beg);
    std::cout << in.rdbuf();  // 直接輸出整個 streambuf

    std::cout << "\n\n--- Last 10% ---\n";
    // 4. 回到先前記錄位置,印出尾部
    in.seekg(start_pos);
    std::cout << in.rdbuf() << '\n';
}

關鍵細節與避坑指南

  • 二進位模式必開:文本模式下 Windows 將 \\r\\n 轉為 \\n,導致位置計算偏移
  • 輸入/輸出指標獨立:fstream 同時有 get 與 put 指標,互不干擾
  • 邊界檢查:seekg(-1, ios::cur) 在檔案開頭會失敗,需檢查 fail()
  • 寬字元流:wifstream 位置單位為寬字元,非位元組
  • rdbuf() 高效輸出:直接輸出緩衝區內容,避免逐字元複製

進階:自訂緩衝區與定位

// 繼承 streambuf 實現記憶體流,支援任意定位
class MemStreamBuf : public std::streambuf {
    std::vector<char> data_;
public:
    MemStreamBuf(const char* ptr, size_t sz) {
        data_.assign(ptr, ptr + sz);
        setg(data_.data(), data_.data(), data_.data() + sz);
    }
    pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode) override {
        // 實現記憶體內定位邏輯
    }
    pos_type seekpos(pos_type pos, std::ios_base::openmode) override {
        // 實現絕對定位
    }
};

效能考量

  • 頻繁 seek 會破壞預讀緩衝,降低順序讀取效能
  • 大檔案隨機存取建議:記憶體映射 (mmap/MapViewOfFile) 或資料庫
  • std::ios::sync_with_stdio(false) 可提升 iostream 速度,但禁用 C stdio 混用

iostream 定位雖較 C 的 fseek 繁瑣,但類型安全、支援狀態檢查、整合 RAII。掌握雙指標模型(get/put)是處理二進位協議、斷點續傳、檔案修補的基礎。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved