4

我有一个 .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();
}

这很好,直到我们遇到字符编码问题。我有一个在编码菜单中设置为“不带 BOM 的 UTF-8”的缓冲区,然后将该文本写入文件:

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

当我打开该文件(在记事本++中)时,编码菜单显示没有BOM的UTF-8,但ß字符已损坏(ß)。

我能够找到我当前缓冲区的编码:

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”表示“没有 BOM 的 UTF-8”和“0”表示“ASCII”,但我找不到 notepad++ 或 Scintilla 认为这些值应该代表什么。

所以我有点不知道下一步该去哪里(Windows 不是我的自然栖息地)。任何人都知道我做错了什么,或者如何进一步调试它?

谢谢。

4

2 回答 2

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');
    }
}
于 2013-08-06T13:27:20.180 回答
0

替代方法:

UTF-8 字符损坏的原因是这一行..

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

.. 使用 读取字符串,它在解码字符串 ( MSDN )[MarshalAs(UnmanagedType.LPStr)]时使用计算机的默认 ANSI 编码。这意味着您会得到一个每个字节一个字符的字符串,它会因多字节 UTF-8 字符而中断。

现在,要将原始 UTF-8 字节保存到磁盘,您只需在写入文件时使用相同的默认 ANSI 编码:

File.WriteAllText(@"C:\Users\davet\BBBBBB.txt", sb.ToString(), Encoding.Default);
于 2016-06-13T00:53:37.407 回答