[英]Produce garbage with using of fread
我想從文件讀取數據。 但是,我遇到了設置NULL終止符的問題。我認為這一行(fileMem [fileSize] = 0;)應該已經解決了。 但是,通過檢查“ fileMem”的值,我仍然會感到困惑。 有人可以幫我發現問題嗎?
我關注了其他有關設置NULL終止符的文章,但不起作用
File *input = fopen(filePath, "r");
fseek(input, 0, SEEK_END);
auto fileSize = ftell(input);
fseek(input, 0, SEEK_SET);
char* fileMem = new char[fileSize+1];
fileMem[fileSize] = 0;// the NULL terminator problem should have been solved here
clearerr(input);
fread(fileMem, fileSize,1, input);
我的代碼有什么問題?
fread讀取的字節數大於fileSize,因為您要指定fileSize的記錄大小,並要求它僅讀取一個文本記錄。 然后,它將最后用實際數據覆蓋0,因此會出現垃圾。
fread返回它實際讀取的字節數,因此您可以分配更大的緩沖區,然后使用fread的返回值確定其中有多少有效(並設置一個空終止符)。
由於它是以這種方式更新數據的,因此我還建議將文件類型更改為二進制(在fopen調用中為“ rb”而不是“ r”)。
發生這種情況的原因是因為fread在文本模式(“ r”而不是“ rb”)下執行文本翻譯,例如回車和換行。
假設您使用的是Windows,我認為問題在於您正在以文本模式打開文件,並使用了意為二進制模式的fread
。 在文本模式下,您讀取的內容可能與文件中的內容不完全相同。 Windows文本文件在文件末尾帶有“ \\ r \\ n”,但是在文本模式下,這兩個字符的組合將轉換為單個字符“ \\ n”。 因此,您計算出的fileSize
太大,因此您的空終止符將放在錯誤的位置。
為了驗證這一點,將fread
更改為:
int nr = fread( fileMen, 1, fileSize, input);
交換中間的args,將使fread
返回讀取的字節數。 如果查看nr
的值,由於行尾轉換,它將小於fileSize
。
在* nix系統上這不是問題,因為在文本模式下沒有翻譯。
當您想使用fread
讀取文件的內容時,必須以二進制模式打開文件。
FILE *input = fopen(filePath, "rb");
^^
否則,您通過使用得到的文件的大小
fseek(input, 0, SEEK_END);
auto fileSize = ftell(input);
將大於fread
可以讀取的字符數。
如果您有CR和LF,按照上述方法,它們將被視為兩個字符,但是fread
只會讀取一個字符。 因此, fread
讀取的內容少於fileSize
字符。 您還可以將fread
行更改為:
// Swap the middle arguments.
// The first argument is supposed to be the size of each object.
// The second argument is supposed to be the number of objects to read.
auto n = fread(fileMem, 1, fileSize, input);
if ( n != fileSize )
{
// Surprise
}
fileMem[n] = '\0';
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.