2013-07-04 17 views
4

我有一個需要獲取當前緩衝區文本的.NET插件。我發現這個page,這顯示了一種方法來做到這一點:Notepad ++ .NET插件 - 獲取當前緩衝區文本 - 編碼問題

public static string GetDocumentText(IntPtr curScintilla) 
{ 
    int length = (int)Win32.SendMessage(curScintilla, SciMsg.SCI_GETLENGTH, 0, 0) + 1; 
    StringBuilder sb = new StringBuilder(length); 
    Win32.SendMessage(curScintilla, SciMsg.SCI_GETTEXT, length, sb); 
    return sb.ToString(); 
} 

這很好,直到我們到達的字符編碼的問題。我有一個是在編碼菜單設定爲「UTF-8無BOM」的緩衝器,並且我編寫的文本到一個文件:

System.IO.File.WriteAllText(@"C:\Users\davet\BBBBBB.txt", sb.ToString()); 

當我打開該文件(在記事本++)編碼菜單顯示UTF -8沒有BOM,但ß字符被破壞(?)。

我能夠儘可能獲得儘可能找到編碼爲我當前緩衝區:

int currentBuffer = (int)Win32.SendMessage(PluginBase.nppData._nppHandle, NppMsg.NPPM_GETCURRENTBUFFERID, 0, 0); 
Console.WriteLine("currentBuffer: " + currentBuffer); 
int encoding = (int) Win32.SendMessage(PluginBase.nppData._nppHandle, NppMsg.NPPM_GETBUFFERENCODING, currentBuffer, 0); 
Console.WriteLine("encoding = " + encoding); 

而顯示爲「4」爲「UTF-8無BOM」和「0」爲「ASCII」,但我無法找到記事本++或Scintilla認爲這些值應該代表什麼。

所以我有點失落的下一步去哪裏(Windows不是我的自然棲息地)。任何人都知道我錯了什麼,或者如何進一步調試它?

謝謝。

回答

4

刪除StringBuilder修復了這個問題。

public static string GetDocumentTextBytes(IntPtr curScintilla) { 

    int length = (int) Win32.SendMessage(curScintilla, SciMsg.SCI_GETLENGTH, 0, 0) + 1; 
    byte[] sb = new byte[length]; 

    unsafe { 
     fixed (byte* p = sb) { 

      IntPtr ptr = (IntPtr) p; 

      Win32.SendMessage(curScintilla, SciMsg.SCI_GETTEXT, length, ptr); 
     } 

     return System.Text.Encoding.UTF8.GetString(sb).TrimEnd('\0'); 
    } 
} 
+0

謝謝@woddle ..完美的作品.. –

0

替代做法:

的原因破壞的UTF-8字符的是,這條線..

Win32.SendMessage(curScintilla, SciMsg.SCI_GETTEXT, length, sb); 

..reads使用[MarshalAs(UnmanagedType.LPStr)]字符串,它使用您的計算機的默認ANSI編碼時解碼字符串(MSDN)。這意味着您會得到一個字符串,每個字節只有一個字符,這會打破多字節UTF-8字符。

現在,原來的UTF-8字節保存到磁盤,你只需要使用相同的默認ANSI編碼寫入文件時:

File.WriteAllText(@"C:\Users\davet\BBBBBB.txt", sb.ToString(), Encoding.Default);