2015-06-13 74 views
3

我無法轉換字節數組的字符串部分。字節數組結構

我的結構是這樣的:

[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(); 
} 

方法到我的字節組轉換成一個結構:

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; 
} 

當我打電話ByteArrayToStructureCreateMessageByteArray()的結果我得到一個id = 60和text =「t」的結構。

爲什麼我不能得到整個字符串,例如「測試」?

編輯: 這是我忘了填寫Flash代碼:

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; 
    } 

回答

4

的問題是在這條線:

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 
+1

我猜想爲MarshalAs屬性添加「CharSet = CharSet.Unicode」也可以。 – cubrr

1

也許如您所願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 
4

在除了其他兩個答案之外,如果您希望text字段中的字符串始終爲Unicode,則可以在您的[StructLayout]屬性中包含CharSet = CharSet.Unicode屬性