順序讀寫只能從頭到尾;隨機存取 透過移動內部位置指標,直接跳躍到任意位元組偏移量進行讀寫,支援資料庫索引、大檔案定位修改等場景。
| 函數 | 原型 | 功能 | 適用模式 |
|---|---|---|---|
rewind | void rewind(FILE *stream); | 移至檔案開頭 (等同 fseek(fp, 0, SEEK_SET)),清除錯誤/EOF 旗標 | 文字/二進位 |
fseek | int fseek(FILE *stream, long offset, int whence); | 相對 whence 移動 offset 位元組 | 二進位模式建議 |
/* 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"。
#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;
}
long ftell(FILE *stream); /* 回傳目前位置指標位元組偏移,失敗回傳 -1L */
fseek 實現「記住位置 → 處理別處 → 返回」模式。fseek 的 offset。fseek(fp, index * record_size, SEEK_SET) → fread/fwrite (本範例)。offset,查詢時先讀索引再 fseek 主檔。fseek(fp, 0, SEEK_END); fwrite(...); fseek(fp, saved_pos, SEEK_SET);fseek(fp, chunk_start, SEEK_SET); 只讀取所需區塊。fseek 成功回傳 0,失敗回傳非 0 (設定 errno)。LONG_MAX (2GB) 的檔案需 fseeko/ftello (POSIX, off_t 64-bit)。_fseeki64/_ftelli64 (MSVC)。fseek/ftell 64-bit 版本建議。std::fstream:seekg/seekp/tellg/tellp 對應,支援 std::streamoff 64-bit。