我正在尝试在 C# 程序(Visual Studio 2010 Express,Windows 7)中使用日语形态分析器MeCab,但编码出现问题。如果我的输入(粘贴到文本框中)是这样的:
一方、広义の动物ネコは、ネコ类(ネコ科)の部分、あるいはその全ての獣を指す包括名字を指す。</pre>然后我的输出(在另一个文本框中)如下所示:
? åè©ž,ã,µå¤‰æŽ¥ç¶š,*,*,*,*,* ? åè©ž,ã,µå¤‰æŽ¥ç¶š,*,*,*,*,* ? åè©ž,ã,µå¤‰æŽ¥ç¶š,*,*,*,*,* ? åè©ž,ã,µå¤‰æŽ¥ç¶š,*,*,*,*,* ? åè©ž,ã,µå¤‰æŽ¥ç¶š,*,*,*,*,* ? åè©ž,ã,µå¤‰æŽ¥ç¶š,*,*,*,*,* ? åè©ž,ã,µå¤‰æŽ¥ç¶š,*,*,*,*,* ? åè©ž,ã,µå¤‰æŽ¥ç¶š,*,*,*,*,* ? åè©ž,ã,µå¤‰æŽ¥ç¶š,*,*,*,*,* ? åè©ž,ã,µå¤‰æŽ¥ç¶š,*,*,*,*,* ? åè©ž,ã,µå¤‰æŽ¥ç¶š,*,*,*,*,* ? åè©ž,ã,µå¤‰æŽ¥ç¶š,*,*,*,*,* ? åè©ž,ã,µå¤‰æŽ¥ç¶š,*,*,*,*,* ? åè©ž,ã,µå¤‰æŽ¥ç¶š,*,*,*,*,* ? åè©ž,ã,µå¤‰æŽ¥ç¶š,*,*,*,*,* ( åè©ž,ã,µå¤‰æŽ¥ç¶š,*,*,*,*,* ? åè©ž,ã,µå¤‰æŽ¥ç¶š,*,*,*,*,* ? åè©ž,ã,µå¤‰æŽ¥ç¶š,*,*,*,*,* ? åè©ž,ã,µå¤‰æŽ¥ç¶š,*,*,*,*,* ? åè©ž,ã,µå¤‰æŽ¥ç¶š,*,*,*,*,* ? åè©ž,ã,µå¤‰æŽ¥ç¶š,*,*,*,*,* ) åè©ž,ã,µå¤‰æŽ¥ç¶š,*,*,*,*,* ? åè©ž,ã,µå¤‰æŽ¥ç¶š,*,*,*,*,* ??????????????????????????? åè©ž,ã,µå¤‰æŽ¥ç¶š,*,*,*,*,* EOS我猜那是一些其他编码的文本被误认为是 UTF-8 编码的文本。但是假设它是 EUC-JP 并使用 Encoding.Convert 将其转换为 UTF-8 并不会改变输出;假设它是 Shift-JIS 并且做同样的事情会产生不同的乱码。此外,虽然它确实在处理文本 - 这就是 MeCab 输出应该被格式化的方式 - 它似乎也没有将输入解释为 UTF-8。如果这样做,输出中就不会出现所有以单字符“复合”开头的相同行,而这显然无法识别。
当我通过 MeCab 的命令行运行这句话时,我又得到了另一组看起来不同的乱码。但是,再一次,它只是左侧的一排问号和括号,所以这不仅仅是 Windows 命令行不支持带有日文字符的字体的问题。再次,它只是没有以 UTF-8 格式读取输入。(我确实以 UTF-8 模式安装了 MeCab。)
代码的相关部分如下所示:
[DllImport("libmecab.dll", CallingConvention = CallingConvention.Cdecl)] 私有外部静态 IntPtr mecab_new2(字符串 arg); [DllImport("libmecab.dll", CallingConvention = CallingConvention.Cdecl)] [返回:MarshalAs(UnmanagedType.AnsiBStr)] 私有外部静态字符串 mecab_sparse_tostr(IntPtr m, string str); [DllImport("libmecab.dll", CallingConvention = CallingConvention.Cdecl)] 私人外部静态无效mecab_destroy(IntPtr m); 私有字符串 meCabParse(字符串 jpnText) { IntPtr mecab = mecab_new2(""); string parsedText = mecab_sparse_tostr(mecab, jpnText); mecab_destroy(mecab); 返回解析文本; }(在摆弄看似合理的东西以查看它们是否有所作为方面,我尝试将“UnmanagedType.AnsiBStr”切换为“UnmanagedType.BStr”,这会给出错误“AccessViolationException was unhandled”,并添加“CharSet= CharSet.Unicode" 到 DllImport 参数,它把输出变成了 "EOS"。)
这就是我进行转换的方式:
// 65001 = UTF-8 代码页,20932 = EUC-JP 代码页 私有字符串转换编码(字符串 sourceString,int sourceCodepage,int targetCodepage) { 编码 sourceEncoding = Encoding.GetEncoding(sourceCodepage); 编码 targetEncoding = Encoding.GetEncoding(targetCodepage); // 将源字符串转换为字节数组 byte[] sourceBytes = sourceEncoding.GetBytes(sourceString); // 将这些字节转换为目标编码 byte[] targetBytes = Encoding.Convert(sourceEncoding, targetEncoding, sourceBytes); // 字节数组转字符数组 char[] targetChars = new char[targetEncoding.GetCharCount(targetBytes, 0, targetBytes.Length)]; //char数组到目标编码的字符串 targetEncoding.GetChars(targetBytes, 0, targetBytes.Length, targetChars, 0); 字符串目标字符串 = 新字符串(目标字符); 返回目标字符串; } 私有字符串 meCabParse(字符串 jpnText) { // 将字符串中的文本从 UTF-8 转换为 EUC-JP jpnText = convertEncoding(jpnText, 65001, 20932); IntPtr mecab = mecab_new2(""); string parsedText = mecab_sparse_tostr(mecab, jpnText); // annnd 转换回 UTF-8 parsedText = convertEncoding(parsedText, 20932, 65001); mecab_destroy(mecab); }建议/嘲讽?