2009-12-02 19 views
8

我有代碼,使用fstream操作二進制文件與二進制標誌設置和使用未格式化的I/O函數讀取和寫入。這在我使用過的所有系統上都能正常工作(文件中的位與預期完全相同),但這些基本上都是美國英語。我一直想知道這些字節在不同的系統上被codecvt修改的可能性。使用C++編寫二進制文件:默認語言環境很重要嗎?

聽起來像標準所說的,使用無格式I/O的行爲與使用sputc/sgetc將字符放入streambuf中的行爲相同。這些會導致streambuf中的溢出或下溢函數被調用,並且聽起來像這些會導致經歷一些codecvt(例如,參見C++標準中的27.8.1.4.3)。對於basic_filebuf,這個codecvt的創建在27.8.1.1.5中指定。這使得它看起來像結果將取決於basic_filebuf.getloc()返回的內容。

所以,我的問題是,我可以假設在一個系統上使用ofstream.write寫出的字符數組可以在另一個系統上使用ifstream.read逐字恢復,無論任何人可能使用哪種語言環境配置系統?我會做如下假設:

  1. 程序正在使用默認 區域(即程序不 更改區域設置本身 在所有)。
  2. 系統都有CHAR_BIT 8,在每個字節內具有相同的位順序,將文件存儲爲八位位組等。
  3. 流對象具有設置的二進制標誌。
  4. 在這個階段,我們不需要擔心任何永久性差異。如果數組中的任何字節將被解釋爲多字節值,則將在稍後的階段根據需要處理字節順序轉換。

如果默認語言環境不能保證在某些系統配置(我不知道,阿拉伯語或其他)上未經修改就通過這個東西,那麼使用C++編寫二進制文件的最佳方式是什麼?

+1

我認爲你應該添加相同的字節順序到你的假設。還是我完全在那裏? – 2009-12-02 08:20:19

+0

@TheScottMachine:Space_C0wb0y是正確的,將相同的字節順序添加到您的假設 – Stan 2009-12-02 23:51:19

+0

謝謝,我添加了一個額外的假設來澄清。 – TheScottMachine 2009-12-03 02:22:49

回答

0

在Windows上應該沒問題,但在其他操作系統上,您還應該檢查行結尾(就像安全一樣)。默認的C/C++語言環境是「C」,它是而不是,具體取決於系統的語言環境。

這不是保證。正如你所瞭解的C/C++編譯器和他們的目標機器差別很大。所以如果你保留所有這些假設,你就等着麻煩來了。改變語言環境的開銷可以忽略不計,除非你試圖讓它每秒數百次。

+0

謝謝,有關默認語言環境的信息是我正在尋找的。 我認爲只要在流上設置了二進制標誌,行結束就不應該出現問題。 – TheScottMachine 2009-12-04 02:40:23

1

如果您設置了二進制標誌,則您寫入的所有內容都將逐字寫入該文件。沒有轉換。你如何解釋字節取決於你(可能還有語言環境)。

還有一件事:在不同的語言環境中有破損的可能性。例如,如果您的數據源基於語言環境創建二進制數據(並且此數據的格式會根據語言環境而改變 - 這是一個糟糕的主意btw)。在不同語言環境的機器上加載數據時會造成麻煩。但這是一個設計錯誤。

如果您只是使用具有相同格式/佈局的標準數據類型/結構,而不管它們在任何地方創建的語言環境都應該是OK。

1

感謝您的幫助。我只是認爲,發佈一些不適合評論的附加信息可能會有幫助。

C++程序的默認語言環境始終爲「C」語言環境(http://www.cplusplus.com/reference/clibrary/clocale/setlocale/)。如果這是您的程序中唯一使用的語言環境,則意味着該行爲不依賴於其所運行的計算機的特定語言環境配置。這也意味着一個char的未格式化的I/O不會經歷任何代碼轉換(儘管wchar_t可能是一個不同的故事)。這意味着(考慮到問題中的假設)讀取和寫入應該允許二進制數據未修改地被恢復。

(來自閱讀文檔)您可以通過調用setlocale(LC_ALL,「」)全局設置應用程序的語言環境以匹配系統默認值,這意味着從該點構建的流將使用系統默認語言環境。要將其設置回「C」語言環境,您可以調用setlocale(LC_ALL,「C」),這意味着這是未來構建的流將使用的語言。你也可以通過調用stream.imbue(locale :: classic())來指定「C」local應該用於已經構建的流。

相關問題