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

C 語言檔案操作教程(十):隨機存取 fseek/rewind/ftell 完整指南與範例

     編輯:C 語言基礎

隨機存取核心:移動檔案位置指標

順序讀寫只能從頭到尾;隨機存取 透過移動內部位置指標,直接跳躍到任意位元組偏移量進行讀寫,支援資料庫索引、大檔案定位修改等場景。

兩大定位函數

函數原型功能適用模式
rewindvoid rewind(FILE *stream);移至檔案開頭 (等同 fseek(fp, 0, SEEK_SET)),清除錯誤/EOF 旗標文字/二進位
fseekint fseek(FILE *stream, long offset, int whence);相對 whence 移動 offset 位元組二進位模式建議

fseek 參數詳解


/* whence 取值 (stdio.h 定義) */
#define SEEK_SET 0  /* 檔案開頭 */
#define SEEK_CUR 1  /* 目前位置 */
#define SEEK_END 2  /* 檔案結尾 */

/* offset 必須為 long,常數加 L 後綴 */
fseek(fp, 100L, SEEK_SET);   /* 移至第 100 位元組 */
fseek(fp, -50L, SEEK_CUR);   /* 向前 50 位元組 */
fseek(fp, 0L, SEEK_END);     /* 移至檔案尾 */

為何二進位模式較安全?

文字模式下 \r\n ↔ \n 轉換導致邏輯位元組數 ≠ 實體位元組數,fseek 計算的偏移量可能落在轉換邊界內,造成讀取錯位。隨機存取請統一開啟 "rb"/"wb"。

完整範例:讀取第 2 筆學生資料 (結構體大小固定)


#include 

struct Student {
    char name[10];
    int  num;
    int  age;
    char addr[15];
} boy, *qq;

int main(void)
{
    FILE *fp;
    qq = &boy;

    if ((fp = fopen("stu_list", "rb")) == NULL) {
        printf("Cannot open file"); return 1;
    }

    rewind(fp);                              /* 確保在開頭 */
    fseek(fp, 1L * sizeof(struct Student), SEEK_SET); /* 跳過第 0 筆 */
    fread(qq, sizeof(struct Student), 1, fp); /* 讀第 1 筆 (索引 1) */

    printf("\n\nname\tnum\tage\taddr\n");
    printf("%s\t%5d\t%7d\t%s\n", qq->name, qq->num, qq->age, qq->addr);

    fclose(fp);
    return 0;
}

輔助函數:ftell — 取得目前位置


long ftell(FILE *stream);   /* 回傳目前位置指標位元組偏移,失敗回傳 -1L */
  • 配合 fseek 實現「記住位置 → 處理別處 → 返回」模式。
  • 二進位模式下回傳值可直接作為 fseek 的 offset。

隨機存取常見模式

  1. 固定長度記錄:fseek(fp, index * record_size, SEEK_SET) → fread/fwrite (本範例)。
  2. 索引檔:主檔變長記錄,建立索引檔記錄每筆 offset,查詢時先讀索引再 fseek 主檔。
  3. 尾端追加後回頭讀:fseek(fp, 0, SEEK_END); fwrite(...); fseek(fp, saved_pos, SEEK_SET);
  4. 大檔案分段處理:fseek(fp, chunk_start, SEEK_SET); 只讀取所需區塊。

錯誤處理與可攜性

  • fseek 成功回傳 0,失敗回傳非 0 (設定 errno)。
  • 超過 LONG_MAX (2GB) 的檔案需 fseeko/ftello (POSIX, off_t 64-bit)。
  • Windows _fseeki64/_ftelli64 (MSVC)。
  • C23 引入 fseek/ftell 64-bit 版本建議。

現代替代方案

  • mmap (POSIX) / MapViewOfFile (Windows):將檔案映射至記憶體,直接用指標隨機存取,OS 自動分頁載入,效能極佳。
  • C++ std::fstream:seekg/seekp/tellg/tellp 對應,支援 std::streamoff 64-bit。
  • SQLite / LMDB:嵌入式 Key-Value/關聯式資料庫,內建索引、事務、ACID。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved