尝试让 libmecab.dll (MeCab) 与 C# 一起使用

2024-03-29

我正在尝试使用日本形态分析仪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);
}
  

建议/嘲讽?


我遇到了这个线程,正在寻找一种方法来做同样的事情。我使用你的代码作为起点这篇博文 http://blog.gebhardtcomputing.com/2007/11/marshal-utf8-strings-in-net.html用于弄清楚如何编组 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;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

尝试让 libmecab.dll (MeCab) 与 C# 一起使用 的相关文章

随机推荐

  • 如何在 Spark Java 中遍历/迭代数据集?

    我正在尝试遍历数据集来进行一些字符串相似度计算 例如 Jaro winkler 或余弦相似度 我将数据集转换为行列表 然后使用 for 语句进行遍历 这不是有效的 Spark 方法 所以我期待 Spark 中有更好的方法 public cl
  • 具有多个 url 路径的 CherryPy MethodDispatcher

    是否MethodDispatcher from CherryPy处理多个 url 路径 我正在尝试做类似下面的事情 但是虽然要求 customers工作正常 要求 orders始终返回 404 没有任何内容与给定的 URI 匹配 class
  • Node.js 中的作业队列

    我正在node js 中寻找一个可以由php 调用的作业队列管理器 这是一个需要发送电子邮件 创建 pdf 文件等的 Web 应用程序 我想对这些应用程序执行异步 php 进程 流程示例 用户请求 php 页面 Php调用作业队列管理器并添
  • 如何订购 kif 测试用例序列?

    我使用了最新版本的 KIF 框架并创建了几个测试用例 KIFTestCase 的子类 我可以知道有什么方法可以改变测试运行序列的顺序吗 例如我有 testA m testB m testC m 当我按下 cmd U 进行测试时 如何制作诸如
  • C# 字段命名指南?

    我将自己编写一些 C 代码 但我想确保遵循最广泛接受的命名约定 以防我想引入其他开发人员 发布我的代码或出售我的代码 现在我遵循微软设定的命名约定 因为它们似乎是最广泛接受的 他们没有提到的一件事是私有字段的命名 在大多数情况下 我看到它们
  • FindNextFile 在 64 位 Windows 上失败?

    使用 C Builder 2007 FindFirstFile 和 FindNextFile 函数似乎无法在 64 位版本的 Vista 和 XP 上找到某些文件 我的测试应用程序是 32 位的 如果我使用它们遍历文件夹 C Windows
  • 任意金额、任意时间的定期付款?

    我们希望找到一个支付提供商 可以让我们做类似于 Hailo 的事情 即 用户注册并向我们提供他们的信用卡详细信息 授权我们向他们的帐户收费 他们只需要这样做once 在 Hailo 的例子中 用户可以随时乘坐出租车并收取任意金额的费用 在合
  • 通过 emacs shell 进行 ssh 吗?

    我想知道是否有人通过 emacs shell 使用 ssh 我能够连接到远程计算机 但无法使用 emacs 文件名 打开文件以使用 emacs 查看 编辑 因为 终端类型 哑 不足以运行 emacs 通常 emacs 会在控制台中打开 通过
  • 尚不支持运算符重载?

    根据 Swift 编程指南 运算符重载是允许的 而且实际上非常通用 但是 我无法让它在操场上工作 例如 Equatable协议想要这样 func lhs Self rhs Self gt Bool 假设我做了一个简单的Location3D
  • VS Code:“isort 服务器在过去 3 分钟内崩溃了 5 次......”

    我可能弄乱了一些环境路径变量 我一边学习 Django 和虚拟环境 一边修改 VS Code 并更改了 Python 安装的目录路径 在弄清楚如何指向 VS Code 的默认 Python 路径时 我删除了一些用户路径变量 然后 伊索开始拒
  • 如何在 google colab 中运行 matlab .m 文件

    我目前正在尝试运行这个存储库https github com Fanziapril mvfnet https github com Fanziapril mvfnet这需要一个步骤 Run the Matlab ModelGeneratio
  • 已确认设计在最新版本中不起作用

    我最近从 Devise 1 2 升级到 1 4 9 除了我的可确认模块之外 一切似乎都正常 电子邮件以及整个过程都有效 但确认页面始终是空白的 它可以工作并确认电子邮件帐户 但不会重定向用户并引发 406 错误 对于错误确认尝试 它也会执行
  • iframe 不工作

    我正在尝试让 Iframe 正常工作 我正在运行 safari 所以它是兼容的 但是当我测试它时 它显示为空白 代码 p Your browser does not support iframes p 使用 尝试一下 编辑器后 我直接从 w
  • 您如何比较 IIS 和 Cassini 作为生产服务器?

    我有一个 ASP NET 网站 当前在 IIS 上运行 现在我想将该站点移至卡西尼号上运行 Cassini 与 IIS 相比有哪些优势 它的缺点是什么 您使用 Cassini 作为生产网络服务器的体验如何 据我所知 您不能在生产中使用 Ca
  • 比较给出错误输出的日期

    我正在创建一个函数来检查充满日期的数据库表中哪个日期小于当前日期 和过去一样 我有 3 个日期来测试该函数 以及它们背后的输出 上个月的日期 2015年4月28日 16 32 00日期尚未到来 11 06 2015 13 12 00上周日期
  • java并发:多生产者一消费者

    我遇到一种情况 不同的线程填充一个队列 生产者 并且一个消费者从该队列中检索元素 我的问题是 当从队列中检索这些元素之一时 某些元素会丢失 丢失信号 生产者代码是 class Producer implements Runnable pri
  • Perl 如何在空格上分割行,除非空格用双引号引起来?

    我有以下字符串 StartProgram 1 C Program Files ABC ABC XYZ CleanProgramTimeout 1 30 我需要一个正则表达式来分割这一行 但忽略 Perl 中双引号中的空格 以下是我尝试过的但
  • Time.advance 记录在哪里?

    在网上查了一下 我发现 RubyTime班级有Time advance 这是在哪里记录的 我在 Ruby API 文档中没有看到任何提及它here http apidock com ruby Time API 文档的搜索功能表明 任何地方都
  • 将进程附加到远程 PC 上正在运行的进程

    我正在开发一个 C 应用程序 该应用程序在远程 PC 上运行 我有 VPN 连接并使用 RDP 会话 我可以登录到该计算机 在那台计算机上 在正在运行的进程旁边 还有两个 msvsmon exe 进程 在任务管理器中具有以下 命令行 条目
  • 尝试让 libmecab.dll (MeCab) 与 C# 一起使用

    我正在尝试使用日本形态分析仪MeCab http mecab sourceforge net 在 C 程序 Visual Studio 2010 Express Windows 7 中 编码出现问题 如果我的输入 粘贴到文本框中 是这样的