如何将字节数组转换为字符串数组?
问题描述:
只是为了澄清事情。我是而不是试图将字节数组转换为单个字符串。我试图将字节数组转换为字符串数组。如何将字节数组转换为字符串数组?
我使用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
类。没有什么关系。
答
如果数据通过Win32 API传递,那么字符串数组将只是一个以null结尾的字符串序列,并在末尾带有一个双空终止符。 (注意字符串将是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使用的其他内部位,如长度,以及带有类型信息的二进制头文件。从剪贴板返回的内容不存在,因此无法反序列化。)
答
如何:
var strings = Encoding.Unicode
.GetString(buffer)
.Split(new[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
你思考['Clipboard.GetFileDropList()'](http://msdn.microsoft.com/en-us/library/system.windows.forms.clipboard。 getfiledroplist.aspx)? – GSerg 2012-07-25 19:11:10
是的,但我想单独使用Windows API,因为WPF中的常规剪贴板功能有问题,正如Web上的许多地方所述。 – 2012-07-25 19:12:09