无法从文件中读取unicode(japanese)

时间:2011-02-10 07:24:58

标签: c++ internationalization character-encoding cjk

您好我有一个包含日文文本的文件,保存为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;  
}  

此程序生成一些随机输出,我在屏幕上看不到任何日文文本。

4 个答案:

答案 0 :(得分: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的变种是什么,都有可能。但一般来说,你必须被用户告知,或者试图猜测,如果你错了就依赖用户来纠正你,或者你必须选择一个固定的字符集并且不要试图支持任何其他

答案 1 :(得分:0)

有人here对俄语字符有同样的问题(他使用basic_ifstream&lt; wchar_t&gt;根据this page,它应该与wifstream相同)。在该问题的评论中,他们还链接到this,这可以帮助您进一步。

如果正确理解了一切,似乎wifstream正确读取了字符,但是程序试图将它们转换为程序运行的任何语言环境。

答案 2 :(得分:0)

两个错误:

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

不要混用coutwcout

同时检查您的文件是否以UTF-16,Little-Endian编码。如果不是这样,你将无法阅读它。

答案 3 :(得分:-1)

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