簡體   English   中英

Ifstream從文本文件中讀取錯誤的字符

[英]Ifstream reads wrong characters from text file

我有以下簡單的代碼,它將文本文件的內容讀入字符數組:

const char* name = "test.txt";
std::cout << "Loading file " << name << std::endl;
std::ifstream file;
file.open(name);
file.seekg (0, std::ios::end);
int length = file.tellg();
std::cout << "Size: " << length << " bytes" << std::endl;
file.seekg (0, std::ios::beg);
char* buffer = new char[length];
file.read(buffer,length);
file.close();
std::cout.write(buffer,length);

但是,似乎ifstream從文件中讀取了錯誤的字符數:每行增加1個字符。 我在網上搜索,看起來在win7文本文件中,每行的末尾除了換行符(\\ n)之外還帶有回車符(\\ r)。 但是,流以某種方式看不到這些\\ r,但仍使用文件中原始數量的符號,並從文件末尾讀取其他字節。 有可能以某種方式解決這個問題嗎?

如果有幫助:我使用MinGW編譯器和Windows 7 64bit。

您可能要以二進制模式打開文件:

file.open(name, ios_base::in | ios_base::binary);

否則,標准庫將為您將每個Windows換行符(CR + LF)轉換為一個\\n

這意味着您可以從文件中讀取的字符數與文件的大小不同。 當您調用read() ,它將讀取盡可能多的字符。 如果無法讀取您請求的字符數,則會設置流的failbit

了解有關打開文件進行binary讀取的信息(google或在此處查看 )。

您是從一些非常錯誤(但普遍)的觀點開始的。 file.tellg()不返回int ; 它返回類型為streampos的實現定義的對象,該對象必須是類類型,並且可以轉換為整數類型,也可以不轉換為整數類型。 而且,如果可以將其轉換為整數類型(並且即使不需要,我也不知道該實現在哪里),則不能保證所得的整數所代表的內容不只是魔術cookie,允許重新尋找到相同的位置。

實際上,在現代計算機上這可能不是什么大問題:Unix和Windows都從文件的開頭返回以字節為單位的偏移量。 在Unix上,這很好用,因為內部表示與外部表示的映射是一對一的。 在Windows中,行尾重新映射:在文本文件中,行尾是兩個字節的序列0x0D,0x0A,在讀取時變成單個char '\\n' streampos (轉換為整數類型)給出了偏移量(以字節為單位),該偏移量是您必須在文件中查找的位置,而不是到達該位置必須讀取的char數。 對於您似乎正在做的事情,這不是問題。 分配的緩沖區可能比必要的要大一些,但是永遠不會太小。

請注意,在大型機上可能並非如此。 從歷史上看,至少,大型機使用面向塊的文件,以及在的積分值streampos可以很容易地東西分成領域,具有一定數目的位的塊號,以及用於字節塊中的偏移的其他位。 根據在字中的排列方式,按您的方式分配的緩沖區可能很容易變得過大幾個數量級,或者如果將偏移量放在高階位上也可能太小。

獲取所需的確切緩沖區大小的唯一可靠方法取決於系統,並且在某些系統(包括Windows)上,除了讀取所有字符並對其進行計數外,可能沒有其他方法。

(之所以要求streampos為類類型是因為,從歷史上看,許多較舊的多字節編碼都具有編碼狀態;您不知道字符之前是什么字符就無法正確對其進行解碼。因此, streampos必須包含兩個不同的信息:文件中要查找的位置以及有關此狀態的信息。不過,我認為今天沒有廣泛使用任何與狀態相關的多字節編碼。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM