[英]Byte array to struct
我在轉換字節數組的字符串部分時遇到問題。
我的結構看起來像這樣:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct Message
{
public int id;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public string text;
}
創建測試字節數組:
private static byte[] CreateMessageByteArray()
{
int id = 69;
byte[] intBytes = BitConverter.GetBytes(id);
string text = "test";
byte[] stringBytes = GetBytes(text);
IEnumerable<byte> rv = intBytes.Concat(stringBytes);
return rv.ToArray();
}
將我的bytearray轉換為結構的方法:
static T ByteArrayToStructure<T>(byte[] bytes) where T : struct
{
var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
var result = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
handle.Free();
return result;
}
當我使用CreateMessageByteArray()
的結果調用ByteArrayToStructure
,我得到一個id = 60和text =“t”的結構。
為什么我沒有得到整個字符串,例如“test”?
編輯:這是我忘記編碼的代碼:
static byte[] GetBytes(string str)
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
問題出在這一行:
byte[] stringBytes = GetBytes(text);
你是如何將字符串轉換為字節數組的? 您可能正在使用Unicode編碼,它將每個字符存儲為兩個字節,並且因為您的字符串是ASCII集,所以每隔一個字節將為零:
byte[] stringBytes = new UnicodeEncoding().GetBytes(text);
// will give you { 't', '\0', 'e', '\0', 's', '\0', 't', '\0' }
這些零錯誤地將編組機制誤認為它們是終端字符,因此字符串在't'
之后結束。
相反,您可以使用ASCII編碼(每個字符存儲一個字節):
byte[] stringBytes = new ASCIIEncoding().GetBytes(text);
// will give you { 't', 'e', 's', 't' }
// but will lose non-ASCII character information
或者您可以使用UTF8編碼(可變長度):
byte[] stringBytes = new UTF8Encoding().GetBytes(text);
// will give you { 't', 'e', 's', 't' }
// and retain non-ASCII character information, but it's somewhat
// trickier to rebuild the string correctly in case of non-ASCII
// information present
除了其他兩個答案之外,如果您希望text
字段中的字符串始終為Unicode,則可以在[StructLayout]
屬性中包含CharSet = CharSet.Unicode
也許GetBytes方法不能按預期工作。 這個linqpad對我來說很好:
void Main()
{
var result = ByteArrayToStructure<Message>(CreateMessageByteArray());
result.Dump();
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct Message
{
public int id;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public string text;
}
private static byte[] CreateMessageByteArray()
{
int id = 69;
byte[] intBytes = BitConverter.GetBytes(id);
string text = "test";
byte[] stringBytes = Encoding.UTF8.GetBytes(text);
IEnumerable<byte> rv = intBytes.Concat(stringBytes);
return rv.ToArray();
}
static T ByteArrayToStructure<T>(byte[] bytes) where T : struct
{
var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
var result = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
handle.Free();
return result;
}
輸出:
id 69
text test
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.