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

C 語言文件隨機讀寫(十):fseek/ftell/fread/fwrite 實現任意位置訪問

     編輯:關於C語言

前言

順序讀寫僅能線性流動,隨機訪問則賦予程序「跳轉至任意位置讀寫」的能力,是數據庫索引、大文件處理、二進制格式解析的基石。本文系統講解 fseek/ftell 定位機制、fread/fwrite 數據塊傳輸,並給出二進制文件隨機讀寫完整範例。

一、隨機訪問四大核心函數

1. fseek:移動文件位置指示器

int fseek(FILE *stream, long offset, int fromwhere);
  • offset:相對 fromwhere 的位元組偏移量(long 支援 >64KB 文件)。
  • fromwhere 三大基準點:
符號常數值含義
SEEK_SET0文件開頭
SEEK_CUR1當前位置
SEEK_END2文件末尾
  • 返回 0 成功,非 0 失敗。
  • **主要用於二進制文件**;文本文件因換行符轉換,位元組偏移不可預測。

2. ftell:獲取當前位置

long ftell(FILE *stream);
  • 返回距文件開頭的位元組偏移量 (long)。
  • 返回 -1 表示出錯。
  • 配合 fseek 實現「記住位置 → 跳轉 → 恢復位置」。

3. fread:讀取數據塊

size_t fread(void *buf, size_t size, size_t count, FILE *stream);
  • 從 stream 讀取 count 個項目,每項 size 位元組,存入 buf。
  • 返回**成功讀取的項目數**(可能小於 count,遇 EOF/錯誤)。
  • 位置指示器自動前移 size * count 位元組。

4. fwrite:寫入數據塊

size_t fwrite(const void *buf, size_t size, size_t count, FILE *stream);
  • 向 stream 寫入 buf 中 count 個項目,每項 size 位元組。
  • 返回成功寫入項目數。
  • 位置指示器自動前移。

二、經典範例:二進制文件第 8 位元組讀取

#include 
#include 

main() {
    FILE *fp;
    if ((fp = fopen("test_b.dat", "rb")) == NULL) {
        printf("Can't open file");
        exit(1);
    }
    fseek(fp, 8, SEEK_SET);  // 從開頭偏移 8 位元組
    fgetc(fp);               // 讀取該位置字符
    fclose(fp);
}

三、結構體數組隨機存取完整範例

#include 
#include 

struct Record {
    int id;
    char name[20];
    double score;
};

int main() {
    FILE *fp = fopen("records.dat", "wb+");
    if (!fp) return 1;

    struct Record recs[3] = {
        {1, "Alice", 92.5},
        {2, "Bob",   87.0},
        {3, "Carol", 95.5}
    };

    /* 寫入 3 條記錄 */
    fwrite(recs, sizeof(struct Record), 3, fp);

    /* 隨機讀取第 2 條 (索引 1) */
    fseek(fp, 1 * sizeof(struct Record), SEEK_SET);
    struct Record r;
    fread(&r, sizeof(struct Record), 1, fp);
    printf("ID=%d Name=%s Score=%.1f\n", r.id, r.name, r.score);

    /* 修改第 1 條並寫回 */
    fseek(fp, 0, SEEK_SET);
    r.score = 93.0;
    fwrite(&r, sizeof(struct Record), 1, fp);

    fclose(fp);
    return 0;
}

四、關鍵技術細節與避坑指南

陷阱說明對策
文本模式用 fseek換行符轉換導致偏移量不準**二進制模式** ("rb"/"wb") 使用隨機訪問
fread/fwrite 返回值未檢查部分讀寫/錯誤靜默失敗必檢查返回值 == count
結構體填充導致跨平台不兼容不同編譯器對齊不同,文件格式不固定使用 #pragma pack 或手動序列化
offset 用 int 而非 long大文件 (>2GB) 溢出堅持 long / off_t / int64_t
ftell 返回 -1 未處理錯誤傳播檢查 if (pos == -1L) handle_error();

五、進階模式:記錄級索引

  • 文件頭部存儲索引表:{key, offset} 陣列。
  • 查找時先讀索引表 → 定位 offset → fseek → fread 讀取完整記錄。
  • 此為 ISAM (Indexed Sequential Access Method) / B+ 樹文件組織的雛形。

總結

fseek/ftell 提供**位元組級定位**,fread/fwrite 提供**類型感知塊傳輸**,二者結合構成 C 語言隨機訪問的核心原語。牢記「二進制模式、檢查返回值、結構體對齊、64位偏移」四大鐵律,即可構建高效、可靠的文件存儲引擎。

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