gpt4 book ai didi

c# - 试图让 libmecab.dll (MeCab) 与 C# 一起工作

转载 作者:太空宇宙 更新时间:2023-11-03 11:35:40 27 4
gpt4 key购买 nike

我正在尝试使用日语词法分析器 MeCab在 C# 程序(Visual Studio 2010 Express、Windows 7)中,编码出了点问题。如果我的输入(粘贴到文本框中)是这样的:

一方、広義の「ネコ」は、ネコ類(ネコ科動物)の一部、あるいはその全ての獣を指す包括的名称を指す。

然后我的输出(在另一个文本框中)如下所示:

?   åè©ž,サ変接続,*,*,*,*,*?   åè©ž,サ変接続,*,*,*,*,*?   åè©ž,サ変接続,*,*,*,*,*?   åè©ž,サ変接続,*,*,*,*,*?   åè©ž,サ変接続,*,*,*,*,*?   åè©ž,サ変接続,*,*,*,*,*?   åè©ž,サ変接続,*,*,*,*,*?   åè©ž,サ変接続,*,*,*,*,*?   åè©ž,サ変接続,*,*,*,*,*?   åè©ž,サ変接続,*,*,*,*,*?   åè©ž,サ変接続,*,*,*,*,*?   åè©ž,サ変接続,*,*,*,*,*?   åè©ž,サ変接続,*,*,*,*,*?   åè©ž,サ変接続,*,*,*,*,*?   åè©ž,サ変接続,*,*,*,*,*(   åè©ž,サ変接続,*,*,*,*,*?   åè©ž,サ変接続,*,*,*,*,*?   åè©ž,サ変接続,*,*,*,*,*?   åè©ž,サ変接続,*,*,*,*,*?   åè©ž,サ変接続,*,*,*,*,*?   åè©ž,サ変接続,*,*,*,*,*)   åè©ž,サ変接続,*,*,*,*,*?   åè©ž,サ変接続,*,*,*,*,*?????????????????????????   åè©ž,サ変接続,*,*,*,*,*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)]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;}

(关于摆弄看似合理的事物以查看它们是否有所作为,我尝试将“UnmanagedType.AnsiBStr”切换为“UnmanagedType.BStr”,这给出了错误“AccessViolationException was unhandled”,并添加“CharSet=CharSet.Unicode”到 DllImport 参数,这将输出变成了“EOS”。)

这就是我进行转换的方式:

// 65001 = UTF-8 codepage, 20932 = EUC-JP codepageprivate 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);}

建议/ mock ?

最佳答案

我偶然发现了这个线程,正在寻找一种方法来做同样的事情。我以您的代码为起点,this blog post了解如何编码 UTF8 字符串。

以下代码为我提供了正确编码的输出:

public class Mecab
{
[DllImport("libmecab.dll", CallingConvention = CallingConvention.Cdecl, CharSet=CharSet.Unicode)]
private extern static IntPtr mecab_new2(string arg);
[DllImport("libmecab.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
private extern static IntPtr mecab_sparse_tostr(IntPtr m, byte[] str);
[DllImport("libmecab.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
private extern static void mecab_destroy(IntPtr m);

public static String Parse(String input)
{
IntPtr mecab = mecab_new2("");
IntPtr nativeStr = mecab_sparse_tostr(mecab, Encoding.UTF8.GetBytes(input));
int size = nativeArraySize(nativeStr) - 1;
byte[] data = new byte[size];
Marshal.Copy(nativeStr, data, 0, size);

mecab_destroy(mecab);

return Encoding.UTF8.GetString(data);
}

private static int nativeArraySize(IntPtr ptr)
{
int size = 0;
while (Marshal.ReadByte(ptr, size) > 0)
size++;

return size;
}
}

关于c# - 试图让 libmecab.dll (MeCab) 与 C# 一起工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6365931/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com