您的位置:首頁>正文

C語言中使用隨機訪問檔,在C語言中程式設計隨機訪問檔I / O

學習資料, 直播課程, 群專業解答老師, 群文件免費源碼 C/C++9群 99816772

除了最簡單的應用程式之外, 大多數程式都必須讀取或寫入檔。 這可能只是為了讀取一個設定檔,

或文本解析器或更複雜的東西。 本文重點介紹在C中使用隨機訪問檔。 基本的文件操作是fopen - 打開文件 - 指定如何打開(讀/寫)和鍵入(二進位/文本)

fclose - 關閉一個打開的檔

fread - 從檔中讀取

fwrite - 寫入文件

fseek / fsetpos - 將檔指標移動到檔中的某處

ftell / fgetpos - 告訴你檔指標的位置

兩種基本的檔案類型是文本和二進位檔案。 在這兩個中, 二進位檔案通常更容易處理。 出於這個原因以及文字檔上的隨機訪問不是你經常需要做的事情, 本教程僅限於二進位檔案。 上面列出的前四個操作是針對文本和隨機訪問檔。 最後兩個只是隨機訪問。

隨機訪問意味著您可以移動到檔的任何部分, 並從中讀取或寫入資料, 而無需讀取整個檔。 數年前,

資料被存儲在大型電腦磁帶上。 在磁帶上的唯一方法是通過讀取磁帶。 然後磁片出現, 現在您可以直接讀取檔的任何部分。

程式設計與二進位檔案

學習資料, 直播課程, 群專業解答老師, 群文件免費源碼 C/C++9群 99816772

二進位檔案是任何長度的檔, 其中的值保存在0到255的範圍內。

這些位元組沒有其他含義, 在文字檔中, 值為13表示回車, 10表示換行, 26表示換行結束檔。 閱讀文字檔的軟體必須處理這些其他的含義。

二進位檔案是一個位元組流, 現代語言傾向於使用流而不是檔。 重要的部分是資料流程而不是來自何處。 在C中, 您可以將資料視為檔或流。 通過隨機訪問, 您可以讀取或寫入檔或流的任何部分。 使用循序存取, 您必須從一開始就像大磁帶一樣迴圈播放檔或流。

此代碼示例顯示了一個簡單的二進位檔案正在寫入, 其中寫入了一個文本字串(char *)。 通常你可以看到這個文字檔, 但你可以寫文本到二進位檔案。

// ex1.c#include #include int main(int argc, char * argv[]){ const char * filename="test.txt"; const char * mytext="Once upon a time there were three bears."; int byteswritten=0;FILE * ft= fopen(filename, "wb") ; if (ft) {fwrite(mytext,sizeof(char),strlen(mytext), ft) ;fclose( ft ) ;} printf("len of mytext = %i ",strlen(mytext)) ; return 0;}

這個例子打開一個二進位檔案進行寫入, 然後在其中寫入一個char *(字串)。

FILE *變數是從fopen()調用返回的。 如果失敗(檔可能存在並且是打開的或唯讀的, 或者檔案名可能有錯), 則返回0。

fopen()命令試圖打開指定的文件。 在這種情況下, 它是在與應用程式相同的資料夾中的test.txt。 如果檔包含路徑, 則所有反斜線必須加倍。 “c: folder test.txt”不正確; 您必須使用“c: folder test.txt”。

由於檔模式為“wb”, 因此此代碼正在寫入二進位檔案。 如果該檔不存在, 則創建該檔, 如果該檔存在, 則刪除該檔中的內容。 如果對fopen的調用失敗, 可能是因為該檔是打開的, 或者該名稱包含無效字元或無效路徑, 則fopen返回值0。

雖然你可以檢查ft是否為非零(成功), 但是這個例子有一個FileSuccess()函數來明確地做到這一點。 在Windows上, 它輸出呼叫的成功/失敗和檔案名。 如果你是在性能之後, 這是有點繁重,

所以你可能會限制這個調試。 在Windows上, 向系統調試器輸出文本的開銷不大。

fwrite(mytext,sizeof(char),strlen(mytext), ft) ;

fwrite()調用輸出指定的文本。 第二個和第三個參數是字元的大小和字串的長度。 兩者都被定義為size_t, 它是不帶正負號的整數。 此調用的結果是寫入指定大小的計數專案。 請注意, 對於二進位檔案, 即使您正在編寫字串(char *), 也不會附加任何回車或換行字元。 如果你想要這些, 你必須明確地將它們包含在字串中。

讀取和寫入檔的檔模式

當你打開一個檔的時候, 你要指定它是如何打開的 - 無論是從新創建它, 還是覆蓋檔, 是文本還是二進位檔案, 讀取還是寫入, 以及是否要附加到檔。 這是通過使用單個字母“r”, “b”, “w”, “a”和“+”以及其他字母組合的一個或多個檔模式說明符完成的。

r - 打開檔進行閱讀。如果該檔不存在或無法找到,則失敗。

w - 打開檔作為空檔進行寫入。如果檔存在,其內容將被銷毀。

a - 在將新資料寫入檔之前,在不刪除EOF標記的情況下打開檔末尾的檔(追加)如果檔不存在,則首先創建檔。

在檔模式中添加“+”可創建三種新模式:

r + - 打開讀取和寫入文件。(該檔必須存在。)

w + - 打開檔作為讀取和寫入的空檔。如果檔存在,其內容將被銷毀。

a + - 打開檔進行閱讀和追加; 附加操作包括在向檔寫入新資料之前移除EOF標記,並且在寫入完成後恢復EOF標記。它首先創建檔,如果它不存在。打開文件閱讀和追加; 附加操作包括在向檔寫入新資料之前移除EOF標記,並且在寫入完成後恢復EOF標記。它首先創建檔,如果它不存在。

檔模式組合

學習資料,直播課程,群專業解答老師,群文件免費源碼 C/C++9群 99816772

此表顯示文本和二進位檔案的檔模式組合。一般來說,你要麼讀或寫文字檔,但不能同時。使用二進位檔案,您可以讀取和寫入相同的檔。下表顯示了您可以對每個組合執行的操作。

閱讀文本

rb +二進位 - 讀取

r +文本 - 讀取,寫入

r + b二進位 - 讀,寫

rb +二進位 - 讀取,寫入

w文本 - 寫,創建,截斷

wb二進位 - 寫,創建,截斷

w +文本 - 讀取,寫入,創建,截斷

w + b二進位 - 讀,寫,創建,截斷

wb +二進位 - 讀,寫,創建,截斷

一個文本 - 寫,創建

AB二進位 - 寫,創建

一個+文本 - 讀,寫,創建

a + b二進位 - 寫,創建

ab +二進位 - 寫,創建

除非你只是創建一個檔(使用“wb”)或唯讀一個檔(使用“rb”),否則你可以使用“w + b”。

一些實現也允許其他字母。例如,微軟允許:

t - 文字模式

c - 提交

n - 不提交

S - 優化循序存取緩存

R - 緩存非順序(隨機訪問)

T - 臨時

D - 刪除/臨時,當檔關閉時會殺死檔。

這些不是可擕式的,所以用它們來防止自己的危險。

隨機存取檔存儲示例

使用二進位檔案的主要原因是靈活性,允許您讀取或寫入檔的任何地方。文字檔只能讓你讀或寫順序。隨著SQLite和MySQL等廉價或免費資料庫的普及,減少了對二進位檔案使用隨機訪問的需求。但是,對檔記錄的隨機訪問有點舊,但仍然有用。

檢查一個例子

假設這個例子顯示了一個索引和資料檔案對存儲在一個隨機訪問檔中的字串。字串是不同的長度,並通過位置0,1等索引。

有兩個void函數:CreateFiles()和ShowRecord(int recnum)。CreateFiles使用大小為1100的char *緩衝區來保存由格式化字串msg組成的臨時字串,後跟n個星號(其中n在5到1004之間)。兩個FILE *都是在變數ftindex和ftdata中使用wb filemode創建的。在創建之後,這些被用來操縱檔。這兩個文件是

的index.dat

data.dat檔

索引檔包含1000個索引類型的記錄; 這是struct indextype,它有兩個成員pos(類型為fpos_t)和size。迴圈的第一部分:

sprintf(text,msg,i,i+5);for ( j=0; j像這樣填補字元串msg。

This is string 0 followed by 5 asterisks :*****This is string 1 followed by 6 asterisks :******

等等。那麼這個:

index.size = (int)strlen(text) ;fgetpos(ftdata, &index.pos ) ;

用字串的長度和資料檔案中將要寫入字串的點填充結構體。

此時,索引檔結構和資料檔案字串都可以寫入到它們各自的檔中。雖然這些是二進位檔案,但它們是按順序寫入的。從理論上講,你可以把記錄寫到當前檔結尾以外的位置,但這不是一個好的技術,可能根本不是可移植的。

最後一部分是關閉這兩個檔。這確保檔的最後部分被寫入磁片。在檔寫入過程中,許多寫操作不直接進入磁片,而是保存在固定大小的緩衝區中。寫入填充緩衝區後,緩衝區的全部內容都寫入磁片。

一個檔刷新功能強制刷新,你也可以指定檔沖洗策略,但這些都是為文字檔。

SHOWRECORD函數

要測試資料檔案中的任何指定記錄是否可以檢索,您需要知道兩件事情:資料檔案中的檔起始位置和檔大小。

這是索引檔所做的。ShowRecord函數打開這兩個檔,找到合適的點(recnum * sizeof(indextype))並獲取一些bytes = sizeof(index)。

fseek( ftindex, sizeof(index)*(recnum) ,SEEK_SET ) ;fread( &index,1,sizeof(index),ftindex) ;

SEEK_SET是一個常量,指定fseek從哪裡完成。還有另外兩個常量定義了這個。

SEEK_CUR - 尋找相對於當前位置

SEEK_END - 從檔末尾查找絕對值

SEEK_SET - 從檔開頭搜索絕對值

您可以使用SEEK_CUR通過sizeof(index)向前移動檔指標。

fseek( ftindex, sizeof(index) ,SEEK_SET ) ;

獲得了資料的大小和位置後,只需要獲取它。

fsetpos( ftdata, &index.pos ) ;fread( text,index.size, 1, ftdata) ;text[ index.size ]='

r - 打開檔進行閱讀。如果該檔不存在或無法找到,則失敗。

w - 打開檔作為空檔進行寫入。如果檔存在,其內容將被銷毀。

a - 在將新資料寫入檔之前,在不刪除EOF標記的情況下打開檔末尾的檔(追加)如果檔不存在,則首先創建檔。

在檔模式中添加“+”可創建三種新模式:

r + - 打開讀取和寫入文件。(該檔必須存在。)

w + - 打開檔作為讀取和寫入的空檔。如果檔存在,其內容將被銷毀。

a + - 打開檔進行閱讀和追加; 附加操作包括在向檔寫入新資料之前移除EOF標記,並且在寫入完成後恢復EOF標記。它首先創建檔,如果它不存在。打開文件閱讀和追加; 附加操作包括在向檔寫入新資料之前移除EOF標記,並且在寫入完成後恢復EOF標記。它首先創建檔,如果它不存在。

檔模式組合

學習資料,直播課程,群專業解答老師,群文件免費源碼 C/C++9群 99816772

此表顯示文本和二進位檔案的檔模式組合。一般來說,你要麼讀或寫文字檔,但不能同時。使用二進位檔案,您可以讀取和寫入相同的檔。下表顯示了您可以對每個組合執行的操作。

閱讀文本

rb +二進位 - 讀取

r +文本 - 讀取,寫入

r + b二進位 - 讀,寫

rb +二進位 - 讀取,寫入

w文本 - 寫,創建,截斷

wb二進位 - 寫,創建,截斷

w +文本 - 讀取,寫入,創建,截斷

w + b二進位 - 讀,寫,創建,截斷

wb +二進位 - 讀,寫,創建,截斷

一個文本 - 寫,創建

AB二進位 - 寫,創建

一個+文本 - 讀,寫,創建

a + b二進位 - 寫,創建

ab +二進位 - 寫,創建

除非你只是創建一個檔(使用“wb”)或唯讀一個檔(使用“rb”),否則你可以使用“w + b”。

一些實現也允許其他字母。例如,微軟允許:

t - 文字模式

c - 提交

n - 不提交

S - 優化循序存取緩存

R - 緩存非順序(隨機訪問)

T - 臨時

D - 刪除/臨時,當檔關閉時會殺死檔。

這些不是可擕式的,所以用它們來防止自己的危險。

隨機存取檔存儲示例

使用二進位檔案的主要原因是靈活性,允許您讀取或寫入檔的任何地方。文字檔只能讓你讀或寫順序。隨著SQLite和MySQL等廉價或免費資料庫的普及,減少了對二進位檔案使用隨機訪問的需求。但是,對檔記錄的隨機訪問有點舊,但仍然有用。

檢查一個例子

假設這個例子顯示了一個索引和資料檔案對存儲在一個隨機訪問檔中的字串。字串是不同的長度,並通過位置0,1等索引。

有兩個void函數:CreateFiles()和ShowRecord(int recnum)。CreateFiles使用大小為1100的char *緩衝區來保存由格式化字串msg組成的臨時字串,後跟n個星號(其中n在5到1004之間)。兩個FILE *都是在變數ftindex和ftdata中使用wb filemode創建的。在創建之後,這些被用來操縱檔。這兩個文件是

的index.dat

data.dat檔

索引檔包含1000個索引類型的記錄; 這是struct indextype,它有兩個成員pos(類型為fpos_t)和size。迴圈的第一部分:

sprintf(text,msg,i,i+5);for ( j=0; j像這樣填補字元串msg。

This is string 0 followed by 5 asterisks :*****This is string 1 followed by 6 asterisks :******

等等。那麼這個:

index.size = (int)strlen(text) ;fgetpos(ftdata, &index.pos ) ;

用字串的長度和資料檔案中將要寫入字串的點填充結構體。

此時,索引檔結構和資料檔案字串都可以寫入到它們各自的檔中。雖然這些是二進位檔案,但它們是按順序寫入的。從理論上講,你可以把記錄寫到當前檔結尾以外的位置,但這不是一個好的技術,可能根本不是可移植的。

最後一部分是關閉這兩個檔。這確保檔的最後部分被寫入磁片。在檔寫入過程中,許多寫操作不直接進入磁片,而是保存在固定大小的緩衝區中。寫入填充緩衝區後,緩衝區的全部內容都寫入磁片。

一個檔刷新功能強制刷新,你也可以指定檔沖洗策略,但這些都是為文字檔。

SHOWRECORD函數

要測試資料檔案中的任何指定記錄是否可以檢索,您需要知道兩件事情:資料檔案中的檔起始位置和檔大小。

這是索引檔所做的。ShowRecord函數打開這兩個檔,找到合適的點(recnum * sizeof(indextype))並獲取一些bytes = sizeof(index)。

fseek( ftindex, sizeof(index)*(recnum) ,SEEK_SET ) ;fread( &index,1,sizeof(index),ftindex) ;

SEEK_SET是一個常量,指定fseek從哪裡完成。還有另外兩個常量定義了這個。

SEEK_CUR - 尋找相對於當前位置

SEEK_END - 從檔末尾查找絕對值

SEEK_SET - 從檔開頭搜索絕對值

您可以使用SEEK_CUR通過sizeof(index)向前移動檔指標。

fseek( ftindex, sizeof(index) ,SEEK_SET ) ;

獲得了資料的大小和位置後,只需要獲取它。

fsetpos( ftdata, &index.pos ) ;fread( text,index.size, 1, ftdata) ;text[ index.size ]='
同類文章
Next Article
喜欢就按个赞吧!!!
点击关闭提示