C 語言無高級語言的「讀全文、改內存、寫回」便利。要在不載入整個文件的前提下,定位特定行並修改,需精準控制文件指針偏移、覆寫長度匹配。本文以修改配置文件 wireless.1.current_state=1 → 0 為例,演示高效單遍掃描、fseek 定位、fprintf 覆寫的完整技術路線。
wireless.1.authmode=1
wireless.1.compression=0
wireless.1.current_ap=ssid12
wireless.1.current_state=1 <-- 目標行:改為 0
wireless.1.devname=ath0
wireless.1.enable_slave1_status=disabled
...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main() {
char linebuffer[512] = {0};
char buffer1[512] = {0}; // 鍵 (等號前)
char buffer2[512] = {0}; // 值 (等號後)
int line_len = 0;
int len = 0; // 累計已讀字節數,即目標行起始偏移
int res;
FILE *fp = fopen("cc.cfg", "r+"); // 讀寫模式,不截斷
if (!fp) { perror("open"); return -1; }
while (fgets(linebuffer, sizeof(linebuffer), fp)) {
line_len = strlen(linebuffer);
len += line_len; // 累計到「當前行結束」的偏移
// 解析 key=value (注意 %[^=] 掃描集)
sscanf(linebuffer, "%[^=]=%[^=]", buffer1, buffer2);
if (strcmp("wireless.1.current_state", buffer1) == 0) {
// 1. 回退到「行首」偏移
len -= line_len;
// 2. 定位文件指針
res = fseek(fp, len, SEEK_SET);
if (res < 0) { perror("fseek"); return -1; }
// 3. 構造新行內容 (長度必須 ≤ 原行長,否則覆蓋下一行)
strcpy(buffer2, "=0");
strcat(buffer1, buffer2); // buffer1 變 "wireless.1.current_state=0"
// 4. 覆寫
fprintf(fp, "%s", buffer1);
fclose(fp);
return 0;
}
}
fclose(fp);
return 0;
}
r+` 模式:讀寫不截斷w+` 會清空文件,**嚴禁**用於就地修改。r+` 保留原內容,指針初始在文件首,讀寫自由切換 (中間需 fflush/fseek 同步)。len` 累計法len += strlen(line),循環檢測到目標行時,len` 指向該行**結尾**。len -= line_len 回退到該行**開頭**,作為 fseek 目標。fgets` 讀取後指針自動後移,`len` 同步記錄指針邏輯位置。sscanf("%[^=]=%[^=]")` 掃描集解析%[^=] 讀取**非等號**字符,遇 = 停止,自動加 \0。strtok 線程安全、不修改源串、單行解析極其高效。fprintf` 從行首寫入,若新串**長於**原行,會覆蓋下一行開頭 → 文件損壞。"=1" → "=0" 等長,安全。若需變長,**必須**讀取剩餘內容到內存,重寫整個文件尾部,或用臨時文件重命名替換。修改前:wireless.1.current_state=1
修改後:wireless.1.current_state=0

圖1 程序運行效果
「單遍掃描 + 偏移回退 + 等長覆寫」是 C 語言就地修改文本文件的**黃金模式**。核心約束:**新舊行長度一致**。若業務涉及變長修改,請採用「讀全量 → 內存修改 → 寫臨時文件 → 原子重命名」模式,保證一致性與崩潰安全。