2011-02-10 105 views
2

嗨我有一個文件包含日文文本,保存爲unicode文件。無法從文件讀取unicode(日語)

我需要從文件中讀取並將信息顯示到標準輸出。

我使用Visual Studio 2008

int main() 
{ 
     wstring line; 
     wifstream myfile("D:\sample.txt"); //file containing japanese characters, saved as unicode file 
     //myfile.imbue(locale("Japanese_Japan")); 
     if(!myfile) 
      cout<<"While opening a file an error is encountered"<<endl; 
     else 
      cout << "File is successfully opened" << endl; 
     //wcout.imbue (locale("Japanese_Japan")); 
     while (myfile.good()) 
     { 
      getline(myfile,line); 
      wcout << line << endl; 
     } 
     myfile.close(); 
     system("PAUSE"); 
     return 0; 
} 

該程序產生一些隨機的輸出,我看不到屏幕上的任何日語文本。

回答

0

有人here與俄羅斯字符同樣的問題(他用basic_ifstream < wchar_t的>至極應根據this page是一樣的wifstream)。在這個問題的意見,他們也鏈接到this這應該會幫助你進一步。

如果將其理解正確的一切,似乎wifstream正確讀取字符,但你的程序試圖將它們轉換成任何語言環境你的程序在運行

0

兩個錯誤:

std::wifstream(L"D:\\sample.txt"); 

也不要混合coutwcout

還要檢查你的文件是以UTF-16,Little-Endian編碼的。如果不是這樣,你將會在閱讀時遇到麻煩。

0

wfstream使用wfilebuf來實際讀取和寫入數據。 wfilebuf默認在內部使用char緩衝區,這意味着文件中的文本被認爲是窄的,並在你看到之前將其轉換爲寬。由於文本實際上很廣泛,所以你會弄得一團糟。

解決方法是用寬的替換wfilebuf緩衝區。

您可能還需要以二進制格式打開文件。

const size_t bufsize = 128; 
wchar_t buffer[bufsize]; 
wifstream myfile("D:\sample.txt", ios::binary); 
myfile.rdbuf()->pubsetbuf(buffer, 128); 

確保流對象超過緩衝區!

看到這裏的細節:http://msdn.microsoft.com/en-us/library/tzf8k3z8(v=VS.80).aspx

+0

實際上,wfstream已經使用了一個專門用於wchar_t的basic_filebuf,事實上,如果情況並非如此,pubsetbuf將會失敗。所以這段代碼除了將緩衝區縮小爲128個寬字符外別無其他。 – bdonlan

+1

@bdonlan wfstream使用的是wfilebuf,它是basic_filebuf 。默認使用char緩衝區,正如我提供的鏈接中所解釋的那樣。 – ymett

5

哦男孩。歡迎來到有趣,有趣的字符編碼世界。

您需要知道的第一件事是您的控制檯在Windows上不是unicode。在控制檯應用程序中您將看到日文字符的唯一方法是如果您將set your non-unicode (ANSI) locale轉換爲日文。這也將使反斜槓看起來像日元符號和打破路徑包含歐洲重音字符的程序使用ANSI Windows API(這是假設已被棄用,當Windows XP出現了,但人們仍然使用到今天...)

所以你要做的第一件事就是建立一個GUI程序。但是我會把這個作爲一個練習留給感興趣的讀者。

二,有很多的方法來表示文字。你首先需要弄清楚使用的編碼。是UTF-8嗎? UTF-16(如果是這樣,是小字還是大字?)Shift-JIS? EUC-JP?如果文件處於little-endian UTF-16格式,則只能使用wstream直接讀取。即使如此,你需要futz with its internal buffer。除了UTF-16之外的任何東西,你都會得到不可讀的垃圾。這在Windows上也是如此!其他操作系統可能有不同的wstream表示。最好不要真的使用wstream

因此,我們假設它是而不是 UTF-16(用於完整的通用性)。在這種情況下,您必須將其讀取爲字符流 - 而不是使用wstream。然後你必須將這個字符串轉換爲UTF-16(假設你正在使用Windows!其他操作系統傾向於使用UTF-8 char*)。在windows上,這可以使用MultiByteToWideChar完成。確保你傳遞正確的代碼頁值,並且CP_ACPCP_OEMCP幾乎總是錯誤的答案。

現在,您可能想知道如何確定哪個代碼頁(即字符編碼)是正確的。簡短的回答是你不需要。沒有看到文本字符串並說明它是哪種編碼的初步方式。當然,可能有提示 - 例如,如果你看到一個byte order mark,那麼它有可能是unicode的任何變種形成該標記。但是一般情況下,你必須被用戶告知,或者試圖猜測,如果你錯了,依靠用戶糾正你,或者你必須選擇一個固定的字符集,而不是試圖支持任何其他。

+0

好吧,如果你設置了truetype字體,實際上控制檯是unicode,但是除非你設置了適當的默認系統區域設置,否則不支持CJK字符。 –

+0

@Yuhong,用於Windows控制檯的字符編碼始終是非Unicode系統區域設置(又名ANSI又名CP_ACP)。它從來不是UTF-16,UTF-8或任何其他unicode語言環境。您選擇的字體中存在unicode轉換表並不會使控制檯本身與unicode兼容。 – bdonlan

+1

實際上,它是OEMCP,而不是ACP,它是控制檯的主要非Unicode編碼。 –