盤古分詞平臺相容性
在使用Lucece.net,需要一箇中文的分片語件,比較好的是盤古分詞,但是我希望能夠在mono的環境下執行,就使用moma檢查了一下盤古分詞
Assembly Version Missing Not Implemented Todo P/Invoke
PanGu.dll 2.3.1.0 3 0 5 0
Calling Method Method Missing from Mono
WordInfo> PreSegment (string) string Strings.StrConv (string, VbStrConv, int)
WordInfo> PreSegment (string) string Strings.StrConv (string, VbStrConv, int)
WordInfo> PreSegment (string) string Strings.StrConv (string, VbStrConv, int)
Calling Method Method with [MonoTodo] Reason
string ReadFileToString (string, Encoding) int Marshal.GetHRForException (Exception) SetErrorInfo
MemoryStream ReadFileToStream (string) int Marshal.GetHRForException (Exception) SetErrorInfo
void WriteStream (string, MemoryStream) int Marshal.GetHRForException (Exception) SetErrorInfo
void WriteLine (string, string) int Marshal.GetHRForException (Exception) SetErrorInfo
void WriteString (string, string, Encoding) int Marshal.GetHRForException (Exception) SetErrorInfo
是StrConv這個函式沒有檢查通過,發現作者使用了 Microsoft.VisualBasic.Strings.StrConv 這個類庫來處理簡體和繁體轉換的問題,這個類用到了windows平臺的特性,所以沒有編譯通過,於是寫了個簡單的簡體繁體轉換的類庫:簡體中文與繁體相互轉換.
是一個Marshal.GetHRForException 用來做io處理出錯的時候判斷的,程式碼如下大概是出現了ERR_PROCESS_CANNOT_ACCESS_FILE錯誤時讓執行緒稍等。程式碼如下
uint hResult = (uint)System.Runtime.InteropServices.Marshal.GetHRForException(e);
if (hResult == ERR_PROCESS_CANNOT_ACCESS_FILE)
{
if (times > 10)
{
//Maybe another program has some trouble with file
//We must exit now
throw e;
}System.Threading.Thread.Sleep(200);
times++;
}
else
{
throw e;
}
查詢MSDN在Marshal,如何:對映 HRESULT 和異常 裡面有一句話 :
COM 方法通過返回 HRESULT 來報告錯誤;.NET 方法則通過引發異常來報告錯誤。 執行時將處理這兩者之間的轉換。 .NET Framework 中的每個異常類都會對映到一個 HRESULT。
也就是說HRESULT是給com來報告錯誤的,.net本身通過引發異常來處理錯誤,而這個IOException對應出來的hresult是
檔案“xxxx”正由另一程序使用,因此該程序無法訪問此檔案。
但是引起這個錯誤的異常根源就是IOException,內部有個私有的HResult無法訪問。只能修改為所有的錯都等待10次,10次之後丟擲異常,所以把外面的if之外的程式碼都註釋掉變成
if (times > 10)
{
//Maybe another program has some trouble with file
//We must exit now
throw e;
}
System.Threading.Thread.Sleep(200);
times++;
這樣兩個不相容的問題就解決了。
盤古分詞Lucene3.03支援
現在盤古分詞給出的Lucene的示例是2.x的版本,而我希望能夠用3.0的版本來整合,其中的區別是PanGuTokenizer.cs
裡面整合的時候會提示Next()
方法沒有找到合適的類來重寫。原因是lucene中next()方法已改成incrementToken()方法.lucene的文件:
This method is called for every token of a document, so an efficient implementation is crucial for good performance. To avoid calls to AttributeSource.addAttribute(Class) and AttributeSource.getAttribute(Class), references to all AttributeImpls that this stream uses should be retrieved during instantiation.
所以只需要修改這個方法,改為使用addAttribute來實現:
這裡有一個已經修改好了的pangu分詞的版本https://github.com/JimLiu/Lucene.Net.Analysis.PanGu .主要程式碼如下,其中next還是原來的方法,去掉override.
新增屬性
private ITermAttribute termAtt;
private IOffsetAttribute offsetAtt;
private IPositionIncrementAttribute posIncrAtt;
private ITypeAttribute typeAtt;
termAtt = AddAttribute<ITermAttribute>();
offsetAtt = AddAttribute<IOffsetAttribute>();
posIncrAtt = AddAttribute<IPositionIncrementAttribute>();
typeAtt = AddAttribute<ITypeAttribute>();
方法實現
public override bool IncrementToken()
{
ClearAttributes();
Token word = Next();
if (word != null)
{
termAtt.SetTermBuffer(word.Term);
offsetAtt.SetOffset(word.StartOffset, word.EndOffset);
typeAtt.Type = word.Type;
return true;
}
End();
return false;
}
以上就是讓lucene.net在mono下使用盤古分詞出現的一些問題。