关于 C# 调用 ICTCLAS 逐句分词报异常的问题解决

来源:互联网 发布:智能电视和网络电视有什么区别 编辑:程序博客网 时间:2024/06/11 10:28

最近在用ICTCLAS2012进行逐句分词,由于代码使用C#编写,且需要逐句进行分词,所以选择调用ICTCLAS50为C#提供的调用接口直接进行分词。这里需要注意的是ICTCLAS50的C#调用接口与ICTCLAS2010的接口形式不同,虽然按照旧接口形式调用依然可以运行,但是一般在分词语句数量达到1300句时,会报异常“尝试读取或写入受保护的内存。这通常指示其他内存已损坏”。

翻出ICTCLAS50的接口文档,发现新的接口形式描述为: 

[DllImport(path, CharSet = CharSet.Ansi, EntryPoint = "ICTCLAS_ParagraphProcess")]        public static extern int ICTCLAS_ParagraphProcess(String sParagraph, int nPaLen,String sResult, eCodeType eCt, int bPOStagged);
但是直接调用一般会出现分词结果为空字符串的问题(若sResult字符串已赋初值为 ""(空字符串)的情况下),虽然旧的问题不再出现,但是分词目的无法达到。考虑到对于C/C++接口中sResult处为输出字符串,且ICTCLAS50.h头文件中提示过需要用户自行分配内存,所以考虑使用StringBuilder类型传值,即如下形式更改其分词接口:

[DllImport(path, CharSet = CharSet.Ansi, EntryPoint = "ICTCLAS_ParagraphProcess")]        public static extern int ICTCLAS_ParagraphProcess(String sParagraph, int nPaLen, StringBuilder sResult, eCodeType eCt, int bPOStagged);

如此即可以将分词结果传出到sResult参数中。这里需要提示的一点是在初始化StringBuilder类型参数的时候建议遵循ICTCLAS50.h中提示,为其分配待分词字符串长度六倍的空间,如:

StringBuilder sb = new StringBuilder(sParagraph.Length * 6);

如此可以避免分配的内存不足的问题。


另外需要其实的一点事是“字符编码类型定义”的问题:

//字符编码类型定义        public enum eCodeType        {            CODE_TYPE_UNKNOWN,//type unknown            CODE_TYPE_ASCII,//ASCII            CODE_TYPE_GB,//GB2312,GBK,GB10380            CODE_TYPE_UTF8,//UTF-8            CODE_TYPE_BIG5//BIG5        }
上面红字加粗部分需要注意,官方接口文档中没有 public,会造成可访问性较低的问题。

如此一来,逐句分词的功能便可正常使用。