记事本++ .NET插件 - 获取当前缓冲区文本 - 编码问题
本文关键字:缓冲区 文本 编码 问题 获取 NET 插件 记事本 | 更新日期: 2023-09-27 18:21:14
我有一个.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"和"ASCII"的"0",但我找不到记事本++或Scintilla认为这些值应该代表什么。
所以我有点迷茫下一步该去哪里(窗户不是我的自然栖息地(。有人知道我做错了什么,或者如何进一步调试它吗?
谢谢。
删除 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');
}
}
替代方法:
UTF-8字符损坏的原因是这一行。
Win32.SendMessage(curScintilla, SciMsg.SCI_GETTEXT, length, sb);
..使用 [MarshalAs(UnmanagedType.LPStr)]
读取字符串,在解码字符串 (MSDN( 时使用计算机的默认 ANSI 编码。这意味着你会得到一个每字节一个字符的字符串,对于多字节 UTF-8 字符,它会中断。
现在,要将原始 UTF-8 字节保存到磁盘,您只需在写入文件时使用相同的默认 ANSI 编码:
File.WriteAllText(@"C:'Users'davet'BBBBBB.txt", sb.ToString(), Encoding.Default);