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

C/C++ 隨機存取檔案處理完全指南

     編輯:關於C++

基本檔案操作函數

函數用途
fopen開啟檔案,指定模式(讀/寫)與類型(二進位/文字)
fclose關閉已開啟檔案
fread讀取檔案
fwrite寫入檔案
fseek/fsetpos將檔案指標移至指定位置
ftell/fgetpos取得檔案指標目前位置

前四個函數適用於文字檔與隨機存取檔,後兩組專用於隨機存取。隨機存取意指可在檔案任意位置間切換讀寫,無須徹底讀完整個檔案。

二進位檔案特性

二進位檔案為任意長度的位元組序列(0~255),位元組本身無特殊含義。相對地,文字檔中 13=CR、10=LF、26=EOF,讀取軟體需解析這些控制碼。現代術語中,二進位檔案視為位元組流,重點在資料流而非來源。C 語言中可視為檔案、資料流或長陣列,隨機存取即可讀寫陣列任意部分。

範例一:寫入二進位檔案

#include <stdio.h>
#include <string.h>

int main() {
    const char *filename = "test.txt";
    const char *mytext = "Once upon a time there were three bears.";
    FILE *ft = fopen(filename, "wb");  // 二進位寫入模式

    if (ft) {
        fwrite(mytext, sizeof(char), strlen(mytext), ft);
        fclose(ft);
    }
    printf("len of mytext = %d\n", (int)strlen(mytext));
    return 0;
}

關鍵點:

  • wb 模式:檔案不存在則建立,存在則清空內容。
  • fwrite 參數:緩衝區、元素大小、元素個數、檔案指標。二進位模式下不自動加入換行符,需自行在字串中包含。
  • 路徑中反斜線需轉義:\"c:\\\\folder\\\\test.txt\"。

檔案開啟模式完整對照表

模式類型讀寫建立截斷
r文字✓
rb二進位✓
r+文字✓✓
r+b / rb+二進位✓✓
w文字✓✓✓
wb二進位✓✓✓
w+文字✓✓✓✓
w+b / wb+二進位✓✓✓✓
a文字✓✓
ab二進位✓✓
a+文字✓✓✓
a+b / ab+二進位✓✓✓

經驗上,除非剛建立或讀完檔案,使用 w+b 較保險。Microsoft 延伸模式尚有 t(文字)、c(認可)、n(非認可)、S(循序優化)、R(隨機優化)、T(暫存)、D(刪除/暫存)。

隨機存取實務:索引/資料檔案模式

資料庫普及前,隨機存取檔案常用於資料處理。小型檔案常採索引/資料雙檔案模式:

  • 資料檔:儲存長短不一的記錄。
  • 索引檔:記錄數與資料檔相同,但每筆記錄固定長度,包含:
struct {
    fpos_t pos;  // 檔案位置
    int    size; // 記錄大小
} indexrec;

fpos_t 為 fsetpos/fgetpos 使用的型別,是 fseek/ftell 的改良版,更適合建立書籤。需計算檔案位置用 fseek,取得目前位置用 ftell(回傳 int)。實務上 fpos_t 可能只是 int,但應使用 fpos_t 型別,它保存檔案指標副本,粒度為 1,可定位至檔案任意位置。

讀寫檔案完整範例

// 寫入結構陣列到二進位檔案
struct Record { int id; char name[32]; double score; };

void WriteRecords(const char *filename, Record *recs, int count) {
    FILE *fp = fopen(filename, "wb");
    if (fp) {
        fwrite(recs, sizeof(Record), count, fp);
        fclose(fp);
    }
}

// 隨機讀取第 n 筆記錄 (0-based)
bool ReadRecord(const char *filename, int n, Record *out) {
    FILE *fp = fopen(filename, "rb");
    if (!fp) return false;
    fseek(fp, n * sizeof(Record), SEEK_SET);
    bool ok = (fread(out, sizeof(Record), 1, fp) == 1);
    fclose(fp);
    return ok;
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved