BinaryFormatter tiết kiệm rất nhiều loại thông tin để có thể deserialize đúng cách. Nếu bạn muốn serialization compact hoặc để comunicate qua một số giao thức nghiêm ngặt, bạn sẽ phải làm điều đó explictly như thế này:
public byte[] ToByteArray()
{
List<byte> result = new List<byte>();
result.AddRange(BitConverter.GetBytes(One));
result.AddRange(BitConverter.GetBytes(Two));
result.AddRange(BitConverter.GetBytes(Three));
result.AddRange(BitConverter.GetBytes(Four));
return result.ToArray();
}
ở đây tôi chuyển đổi mỗi UInt32 của bạn vào mảng byte và lưu nó trong kết quả mảng.
Sửa
Hóa ra có một cách khác bằng cách sử dụng struct
và Marshal
Trước tiên, bạn hãy struct
và đánh dấu nó với các thuộc tính như thế:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct MyStruct
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
public string StringField;
public int IntField;
}
Đây LayoutKind.Sequential
nói với clr để giữ các lĩnh vực trong bộ nhớ theo thứ tự như tuyên bố. Nếu không có Pack = 1
cấu trúc có thể mất nhiều bộ nhớ hơn mức yêu cầu. Giống như struct
với một trường short
và một byte
chỉ cần 3 byte, nhưng theo mặc định kích thước của nó sẽ là 4 (bộ xử lý có hướng dẫn thao tác đơn byte, 2 byte và 4 byte, clr hi sinh một byte cho mỗi thể hiện cấu trúc để giảm số lượng hướng dẫn về mã máy bằng một nửa). Bây giờ bạn có thể sử dụng Marshal
để sao chép byte:
public static byte[] GetBytes<T>(T str)
{
int size = Marshal.SizeOf(str);
var bytes = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(size);
try
{
Marshal.StructureToPtr(str, ptr, true);
Marshal.Copy(ptr, bytes, 0, size);
return bytes;
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
Mọi thứ hoạt động tốt với các loại đơn giản. Đối với các loại phức tạp như string
, bạn sẽ phải sử dụng thuộc tính MarshalAs
và việc sử dụng nó phức tạp hơn một chút (Ví dụ: tôi đã nói với clr để marshal chuỗi là mảng có kích thước cố định là 50 byte).
Cần 16 byte. Bất kỳ đề xuất làm thế nào tôi nên sử dụng StreamWriter ?? –
Tôi đã chỉnh sửa câu trả lời của mình. Mảng byte kết quả phải là 16 byte nếu bạn làm theo cách tôi đề xuất. Lưu ý rằng đây chỉ là mã mẫu. Tôi chưa thử nghiệm nó, cũng không sử dụng câu lệnh 'using' mà bạn nên sử dụng cho các đối tượng thực hiện' IDisposable' như 'MemoryStream'. Bạn có thể quyết định thực hiện chức năng này trong đối tượng Foo của bạn, vì vậy bạn có thể gọi foo.Serialize() để nhận mảng byte của bạn. –