我正在尝试使用日本形态分析仪MeCab http://mecab.sourceforge.net/在 C# 程序(Visual Studio 2010 Express、Windows 7)中,编码出现问题。如果我的输入(粘贴到文本框中)是这样的:
一方、広義の「ネコ」は、ネコ類(ネコ科動物)の一部、あるいはその全ての獣を指す包括的名称を指す。
然后我的输出(在另一个文本框中)如下所示:
? åè©ž,サ変接続,*,*,*,*,*
? åè©ž,サ変接続,*,*,*,*,*
? åè©ž,サ変接続,*,*,*,*,*
? åè©ž,サ変接続,*,*,*,*,*
? åè©ž,サ変接続,*,*,*,*,*
? åè©ž,サ変接続,*,*,*,*,*
? åè©ž,サ変接続,*,*,*,*,*
? åè©ž,サ変接続,*,*,*,*,*
? åè©ž,サ変接続,*,*,*,*,*
? åè©ž,サ変接続,*,*,*,*,*
? åè©ž,サ変接続,*,*,*,*,*
? åè©ž,サ変接続,*,*,*,*,*
? åè©ž,サ変接続,*,*,*,*,*
? åè©ž,サ変接続,*,*,*,*,*
? åè©ž,サ変接続,*,*,*,*,*
( åè©ž,サ変接続,*,*,*,*,*
? åè©ž,サ変接続,*,*,*,*,*
? åè©ž,サ変接続,*,*,*,*,*
? åè©ž,サ変接続,*,*,*,*,*
? åè©ž,サ変接続,*,*,*,*,*
? åè©ž,サ変接続,*,*,*,*,*
) åè©ž,サ変接続,*,*,*,*,*
? åè©ž,サ変接続,*,*,*,*,*
????????????????????????? åè©ž,サ変接続,*,*,*,*,*
EOS
我猜想其他编码中的文本会被误认为是 UTF-8 编码的文本。但假设它是 EUC-JP 并使用 Encoding.Convert 将其转换为 UTF-8 不会改变输出;假设它是 Shift-JIS 并且执行相同的操作会产生不同的乱码。另外,虽然它确实在处理文本——这就是 MeCab 输出应该被格式化的方式——但它似乎也没有将输入解释为 UTF-8。如果这样做的话,输出中就不会有所有以单字符“化合物”开头的相同行,而它显然无法识别这一点。
当我通过 MeCab 的命令行运行该句子时,我得到了另一组看起来不同的乱码。但是,同样,它只是从左侧向下的一排单个问号和括号,因此这不仅仅是 Windows 命令行不支持日语字符字体的问题;而是 Windows 命令行不支持日语字符的问题。再说一遍,它只是不读取 UTF-8 格式的输入。 (我确实以 UTF-8 模式安装了 MeCab。)
代码的相关部分如下所示:
[DllImport("libmecab.dll", CallingConvention = CallingConvention.Cdecl)]
private extern static IntPtr mecab_new2(string arg);
[DllImport("libmecab.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.AnsiBStr)]
private extern static string mecab_sparse_tostr(IntPtr m, string str);
[DllImport("libmecab.dll", CallingConvention = CallingConvention.Cdecl)]
private extern static void mecab_destroy(IntPtr m);
private string meCabParse(string jpnText)
{
IntPtr mecab = mecab_new2("");
string parsedText = mecab_sparse_tostr(mecab, jpnText);
mecab_destroy(mecab);
return parsedText;
}
(在摆弄看似合理的东西以查看它们是否有所作为方面,我尝试将“UnmanagementType.AnsiBStr”切换为“UnmanagementType.BStr”,这给出了错误“AccessViolationException未处理”,并添加“CharSet= CharSet.Unicode” 到 DllImport 参数,这将输出变成“EOS”。)
这就是我一直在进行转换的方式:
// 65001 = UTF-8 codepage, 20932 = EUC-JP codepage
private string convertEncoding(string sourceString, int sourceCodepage, int targetCodepage)
{
Encoding sourceEncoding = Encoding.GetEncoding(sourceCodepage);
Encoding targetEncoding = Encoding.GetEncoding(targetCodepage);
// convert source string into byte array
byte[] sourceBytes = sourceEncoding.GetBytes(sourceString);
// convert those bytes into target encoding
byte[] targetBytes = Encoding.Convert(sourceEncoding, targetEncoding, sourceBytes);
// byte array to char array
char[] targetChars = new char[targetEncoding.GetCharCount(targetBytes, 0, targetBytes.Length)];
//char array to targt-encoded string
targetEncoding.GetChars(targetBytes, 0, targetBytes.Length, targetChars, 0);
string targetString = new string(targetChars);
return targetString;
}
private string meCabParse(string jpnText)
{
// convert the text from the string from UTF-8 to EUC-JP
jpnText = convertEncoding(jpnText, 65001, 20932);
IntPtr mecab = mecab_new2("");
string parsedText = mecab_sparse_tostr(mecab, jpnText);
// annnd convert back to UTF-8
parsedText = convertEncoding(parsedText, 20932, 65001);
mecab_destroy(mecab);
}
建议/嘲讽?