2010-10-18 172 views
1

我有一個包含多個記錄的CSV格式的二進制文件。每條記錄都以user_name,last_name,first_name,num_wins,num_losses,num_ties的形式輸入。我正在創建一種方法來更新某些球員的勝利,損失和關係記錄。用戶輸入要更改的用戶名,然後輸入對贏,損失和關係的更改。例如smithj 4 5 1.這將找到smithj記錄併爲勝利等添加4等。C程序:如何正確使用lseek()或fseek()來修改文件的某個部分?

如何使用lseek或fseek完成此操作?還是有另一種方法來做到這一點?

+2

CSV通常包含純文本。它是逗號分隔值的簡稱。無論如何,除非你知道那裏是什麼,否則lseek和fseek不會跳到正確的位置。此外,如果您增加記錄大小(例如,當您添加1到9並獲得10)時,您將遇到麻煩。 – xscott 2010-10-18 02:20:19

+0

如果你需要堅持使用CSV,我會計劃逐行閱讀文件,並逐行寫入。當你找到一個匹配的,你可以適當地改變它。 – xscott 2010-10-18 02:21:17

+0

用真實的數據庫格式真正解決了這類問題。我推薦Sqlite。但是,如果你剛剛入門,這將是一個學習曲線。 – xscott 2010-10-18 02:22:15

回答

1

響應例如寫了以請求 - 假設固定大小記錄:

enum { RECSIZE = 256 }; 

char buffer[RECSIZE]; 
FILE *fp = ...; // File to read from and write to 

int recnum = 37; // Counting from record 0 
long offset = recnum * RECSIZE; 

if (fseek(fp, offset, SEEK_SET) != 0) 
    ...error... 
if (fread(buffer, sizeof(buffer), 1, fp) != 1) 
    ...error... 
...modify buffer... 
if (fseek(fp, offset, SEEK_SET) != 0) 
    ...error... 
if (fwrite(buffer, sizeof(buffer), 1, fp) != 1) 
    ...error... 

重複從recnum聲明代碼來結束一次必須修改每個記錄(認爲循環)。

對於可變大小的記錄,在編輯它們時會改變大小,因此您必須更加努力地工作 - 以便將舊文件一次複製到內存中一條記錄可能會更簡單,適當地修改記錄,然後將修改後的記錄寫入新文件。

1

假設文件是​​一個文本文件,那麼你將不得不將行填充到一個固定的寬度。然後使用lseek(),read()和write()來修改這些行。每條線具有恆定的長度是至關重要的:它允許您計算每條線的起始位置。

1

如果每條記錄的字節數相同,這很容易做到。 你會檢查第一條記錄,看它是否匹配,如果不匹配,則執行fseek(f, record_size, SEEK_CUR);並檢查下一條記錄。

如果每條記錄的字節數不同,我能想到的就是您將記錄的字節數放在實際記錄之前。然後讀取它,然後fseek()得到下一個記錄大小的許多字節。我已經看到了一些二進制文件格式,這使得事情變得相當容易。

+1

您必須閱讀以及尋找 - 或者更常見的是,您閱讀,直到找到,然後倒帶(使用fseek())到記錄的開頭,以便覆蓋它。如果您只閱讀記錄的一部分,則可能需要在讀取之間尋找。但是,磁盤驅動器可能會以4096字節長的塊(某些功率在512字節到16千字節之間的2個塊)讀取,除非您的記錄時間特別長,否則您只需在程序中通過讀取較少數據比全記錄;實際的磁盤流量不會受到部分記錄讀取的影響。 – 2010-10-18 03:02:17

+0

有人可以寫一個如何做到這一點的例子嗎? – 2010-10-18 03:25:13

相關問題