iostream 提供雙重定位機制,對應 C 標準庫 fseek/ftell:
streampos pos = tellg(); ... seekg(pos);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';
}
\\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)是處理二進位協議、斷點續傳、檔案修補的基礎。