我是 C 編程的初學者,我對如何處理檔案有一些疑問。
讓我們假設我們有一個存盤了 N 個 int 值的二進制檔案。讓我們假設我們要讀取檔案中的第 i 個值。
使用 fseek 將檔案指標定位到第 i 個 int 值并在 fseek 之后讀取它而不是使用 i fread 呼叫序列有什么真正的好處嗎?
直覺上,我認為 fseek 更快。但是函式如何在不讀取中間資訊的情況下找到檔案中的第 i 個值呢?
我認為這是依賴于實作的。所以,我試圖找到 fseek 函式的實作,但沒有取得多大成功。
uj5u.com熱心網友回復:
使用 fseek 將檔案指標定位到第 i 個 int 值并在 fseek 之后讀取它而不是使用 i fread 呼叫序列有什么真正的好處嗎?
是的,如果您想從檔案中讀取一個值并且您知道它在哪里,那么就沒有理由讀取任何其他內容。
直覺上,我認為 fseek 更快。但是函式如何在不讀取中間資訊的情況下找到檔案中的第 i 個值呢?
你的直覺是正確的,如果你讀取一個值,它會比讀取多個值更有效。它找值的方法很簡單,一般來說檔案中的每個位置對應1個位元組,如果你傳遞一個偏移量,比如7,下次讀取將從第8個位元組開始,想象你的檔案有以下資料:
-58 10 12 14 7 9
^ ^
| |
0 offset of 7
fseek(fp, 7, SEEK_SET);
if(fscanf(fp,"%d",&num) == 1 ){
printf("%d", num);
}
將輸出12.
檔案指示符設定為第 7 位,然后從下一個位元組開始讀取。就好像您有一個陣列并且想要訪問第 7 個位置,您只需使用arr[7].
我認為這是依賴于實作的。
盡管有一些小細節可以實作定義,但整體行為是標準化的。
§7.21.9.2 fseek 函式
概要
1.
#include <stdio.h> int fseek(FILE *stream, long int offset, int whence);描述:
fseek 函式為流指向的流設定檔案位置指示符。如果發生讀取或寫入錯誤,則會設定流的錯誤指示符并且 fseek 失敗。
對于二進制流,新位置(以檔案開頭的字符為單位)是通過將偏移量添加到由 wherece 指定的位置獲得的。如果 wherece 是 SEEK_SET,則指定的位置是檔案的開頭,如果是 SEEK_CUR,則是檔案位置指示符的當前值,如果是 SEEK_END,則是檔案的結尾。二進制流不需要有意義地支持具有 SEEK_END 值的 fseek 呼叫。
對于文本流,偏移量應為零,或偏移量應為較早成功呼叫與同一檔案關聯的流上的 ftell 函式回傳的值,且 wherece 應為 SEEK_SET。
確定新位置后,成功呼叫 fseek 函式會撤消 ungetc 函式對流的任何影響,清除流的檔案結束指示符,然后建立新位置。在成功呼叫 fseek 之后,更新流上的下一個操作可能是輸入或輸出。
回傳:
- fseek 函式僅對無法滿足的請求回傳非零值。
uj5u.com熱心網友回復:
但是函式如何在不讀取中間資訊的情況下找到檔案中的第 i 個值呢?
它沒有。由您提供正確的(絕對或相對)偏移量。例如,您可以請求將檔案指標前移i*sizeof(X)。
它仍然需要遵循檔案所在的扇區鏈來找到正確的扇區,但這不需要讀取這些扇區。該元資料存盤在檔案本身之外。
使用 fseek 將檔案指標定位到第 i 個 int 值并在 fseek 之后讀取它而不是使用 i fread 呼叫序列有什么真正的好處嗎?
每個級別都有潛在的好處。
通過查找,系統可能不得不從磁盤中讀取更少的內容。系統以扇區為單位從磁盤讀取,因此由于快取,短尋道可能沒有這種好處。但是在整個扇區中查找會減少需要從磁盤獲取的資料量。
同樣,通過查找,stdio 庫對作業系統的請求更少。stdio 庫通常讀取比它需要的更多,以便以后呼叫fread不需要接觸作業系統或磁盤。短查找可能不需要進行任何系統呼叫,但在緩沖資料末尾以外查找可以減少從作業系統獲取的資料總量。
最后,在使用 時,跳過的資料根本不需要從 stdio 庫的緩沖區復制到用戶的緩沖區fseek,無論您搜索多遠。
哦,我們不要忘記您正在考慮i -1 讀取而不是大讀取。這些讀取中的每一個都消耗 CPU,無論是在庫(錯誤檢查)中還是在呼叫者中(錯誤處理)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/336472.html
上一篇:C語言保存/加載功能
