如何将字节数组转换为字符串数组?

3

首先澄清一些事情。我不是试图将字节数组转换为单个字符串,而是尝试将字节数组转换为字符串数组。

我正在使用GetClipboardData API从剪贴板获取一些数据,然后将数据作为字节数组从内存中复制。当你复制多个文件(因此是CF_HDROP剪贴板格式)时,我想将这个字节数组转换为所复制的文件的字符串数组。

这是我的代码:

//Get pointer to clipboard data in the selected format
var clipboardDataPointer = GetClipboardData(format);

//Do a bunch of crap necessary to copy the data from the memory
//the above pointer points at to a place we can access it.
var length = GlobalSize(clipboardDataPointer);
var @lock = GlobalLock(clipboardDataPointer);

//Init a buffer which will contain the clipboard data
var buffer = new byte[(int)length];

//Copy clipboard data to buffer
Marshal.Copy(@lock, buffer, 0, (int)length);

GlobalUnlock(clipboardDataPointer);

snapshot.InsertData(format, buffer);

现在,这是我的代码,用于之后读取缓冲区数据。
var formatter = new BinaryFormatter();
using (var serializedData = new MemoryStream(buffer))
{
    paths = (string[]) formatter.Deserialize(serializedData);
}

这样做行不通,会抛出一个异常并提示流中没有二进制头。我猜测这是因为它不知道反序列化成哪种类型。
我已经尝试过查找 Marshal 类,但似乎都没有相关的信息。

你是否在考虑使用Clipboard.GetFileDropList() - GSerg
是的,但我想单独使用Windows API,因为WPF中的一般剪贴板功能存在缺陷,正如网上许多地方所描述的那样。 - Martin Sax
2个回答

2
如果数据是通过 Win32 API 传输的,那么字符串数组将只是以双空字符结尾的一系列以空字符结尾的字符串。请注意,这些字符串将是 UTF-16 编码的,每个字符占用两个字节。您需要将字符串逐个提取到数组中。
这里要使用的方法是Marshal.PtrToStringUni,而不是使用 Marshal.Copy,因为它可以在 IntPtr 上工作。它会从您的 IntPtr 中提取一个字符串,直到第一个空字符,并将其复制到一个字符串中。
思路是不断提取单个字符串,然后将 IntPtr 前进到下一个字符串的开头处,直到缓冲区耗尽。我没有测试过这个代码,它可能还有改进的空间(特别是我认为有一种更聪明的方法来检测缓冲区的末尾),但基本思想如下:
var myptr = GetClipboardData(format);
var length = GlobalSize(myptr);

var result = new List<string>();

var pos = 0;
while ( pos < length )
{
    var str = Marshal.PtrToStringUni(myptr);
    var count = Encoding.Unicode.GetByteCount(str);

    myptr = IntPtr.Add(myptr, count + 1);
    pos += count + 1;

    result.Add(str);
}

return result.ToArray();

顺便说一下:你的反序列化无法正常工作是因为序列化string[]不仅会将字符写成字节,还会写出字符串数组的结构,包括.NET使用的长度和二进制标头中的类型信息等额外的内部位。从剪贴板获取的内容没有这些内容,因此无法进行反序列化。


1
这个怎么样?
var strings = Encoding.Unicode
    .GetString(buffer)
    .Split(new[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接