2012-05-07 5 views
1

Когда я пытаюсь преобразовать объект в массив байтов, я получаю wierd массив. это код:Преобразование объектов в байты

 using (MemoryStream ms = new MemoryStream()) 
     { 
      BinaryFormatter bf = new BinaryFormatter(); 
      bf.Serialize(ms, obj); 
      Console.WriteLine(ByteArrayToString(ms.ToArray())); 
     } 
//int obj = 50; 

//string ByteArrayToString(byte[] byteArr) the functionality of this method is pretty obvious 

результат заключается в следующем:

«00 01 00 00 00 FF FF FF FF 01 00 00 00 00 00 00 00 04 01 00 00 00 0C 53 79 73 74 65 6D 2E 49 6E 74 33 32 01 00 00 00 07 6D 5F 76 61 6C 75 65 00 08 32 00 00 00 0B «

Может кто-нибудь объяснить мне ПОЧЕМУ? :) оптимальный результат должен быть только« 32 00 00 00 ".

+0

Это именно то, чего я ожидал бы. Вы конвертируете объект 'MemortyStream' вместо целочисленной переменной' obj' в массив 'byte'. Существует 'integer' to Byte []' Я предлагаю вам использовать его. Я должен проголосовать за этот вопрос, потому что кажется, что вы не потратили времени, пытаясь понять это. –

+0

@ Ramhound: ваше объяснение не имеет смысла, поскольку OP явно * не * сериализует «MemoryStream».См. ['BinaryFormatter.Serialize'] (http://msdn.microsoft.com/en-us/library/c5sbs8z9.aspx). – user7116

ответ

8

Поскольку сериализатор должен предоставить достаточную информацию для десериализации данных назад, он должен содержать некоторые метаданные о сериализованном объекте. В частности,

53 79 73 74 65 6D 2E 49 6E 74 33 32 

часть выступает за System.Int32

Если вы используете BinaryWriter и его Write(Int32) метод вместо этого, вы получите желаемый эффект: ваш поток памяти будет содержать только четыре байта из вашего целого. Вы не сможете десериализовать его, не зная, что вы написали Int32 в поток.

+0

+1, я думаю, что ОП немного нечеткая с целью сериализации. – user7116

+0

Хм, что, если я не знаю точно типа «obj» во время компиляции? Поскольку я фактически использую его для преобразования объекта Object, который представляет другой тип (который известен только во время выполнения) ץ – TalBin

+1

@TalBin Затем вам нужно включить * некоторую * информацию, чтобы идентифицировать тип этого объекта для кода, который преобразует двоичные данные обратно в объект. Это необязательно должны быть данные, предоставленные бинарным форматированием - вы можете придумать свою собственную схему, но она должна быть там. Например, если вы знаете, что все, что вы можете передать, это либо int, либо строка, либо double, вы можете префикс дополнительного байта для ваших данных и установить его в 1, если остальное - строка, 2 id является int, а 3, если остальное является двойным. Детали полностью зависят от вас, но какая-то информация должна быть там. – dasblinkenlight

0

Дополнительным материалом в результатах будет объект BinaryFormatter. Вы не просто выводите int obj = 50, вы также выводите все, что включено в BinaryFormatter.

+2

-1, нет потока памяти, который * записывается в * не то, что отправляется в поток. – user7116

+0

Справа, с ошибкой, предназначалась для ввода BinaryFormatter и была отвлечена. – tmesser

+0

Чтобы уточнить, * дополнительный материал * представляет собой деталь реализации бинарной сериализации. Это позволяет 'BinaryFormatter' правильно десериализовать граф объектов. На самом деле сам экземпляр «BinaryFormatter» не сериализуется рядом с объектом, а метаданные о количестве и типах объектов. – user7116

2

Вы объединяете BinaryFormatter сериализацию с объекта в формате памяти. То, что написано в потоке, является просто деталью реализации BinaryFormatter и не следует полагаться на любую межпроцессную связь, не используя BinaryFormatter.

Если вы ищете представление байтов встроенных типов, используйте BitConverter.GetBytes (для строк используйте соответствующий Encoding.GetBytes).

1

Сериализованный массив байтов имеет как данные, так и информацию о типе. Вот почему вы получаете больше информации, чем вы ожидаете. Это необходимо для последующего десериализации.

0

Процесс сериализации использует дополнительные байты для хранения информации о типах - это единственный способ обеспечить десериализацию сериализованных данных на одни и те же объекты того же типа. Если вы абсолютно уверены в том, что делаете и хотите избежать лишних байтов, вы можете использовать свою собственную сериализацию и сделать свой форматтер и сериализаторы, что очень сложно. Или, вы можете использовать маршалинг:

var size = Marshal.SizeOf(your_object); 
// Both managed and unmanaged buffers required. 
var bytes = new byte[size]; 
var ptr = Marshal.AllocHGlobal(size); 
// Copy object byte-to-byte to unmanaged memory. 
Marshal.StructureToPtr(font.LogFont, ptr, false); 
// Copy data from unmanaged memory to managed buffer. 
Marshal.Copy(ptr, bytes, 0, size); 
// Release unmanaged memory. 
Marshal.FreeHGlobal(ptr); 

и преобразовать байт объекта:

var bytes = new byte[size]; 
var ptr = Marshal.AllocHGlobal(size); 
Marshal.Copy(bytes, 0, ptr, size); 
var your_object = (YourType)Marshal.PtrToStructure(ptr, typeof(YourType)); 
Marshal.FreeHGlobal(ptr); 

Это довольно медленно и небезопасно для использования в большинстве случаев, но это самый простой способ строго преобразовать объект в байте [] без реализации сериализации и без атрибута [Serializable].

Смежные вопросы