How to convert an object to an array of bytes in C #

I have a set of objects that I need to write to a binary file.

I need the bytes in the file to be compact, so I cannot use BinaryFormatter . BinaryFormatter generates various information for deserialization needs.

If i try

 byte[] myBytes = (byte[]) myObject 

I get an exception at runtime.

I need this to be fast, so I would prefer not to copy byte arrays. I would just like the actor byte[] myBytes = (byte[]) myObject works!

OK, to be clear, I cannot have any metadata in the output file. Just bytes of an object. A packed object object. Based on the answers I received, it looks like I will write a low-level Buffer.BlockCopy code. Possibly using unsafe code.

+55
c #
Sep 18 '09 at 19:58
source share
12 answers

Converting an object to an array of bytes:

 // Convert an object to a byte array public static byte[] ObjectToByteArray(Object obj) { BinaryFormatter bf = new BinaryFormatter(); using (var ms = new MemoryStream()) { bf.Serialize(ms, obj); return ms.ToArray(); } } 

You just need to copy this function into your code and send it the object that you need to convert to an array of bytes. If you need to convert the byte array to an object again, you can use the function below:

 // Convert a byte array to an Object public static Object ByteArrayToObject(byte[] arrBytes) { using (var memStream = new MemoryStream()) { var binForm = new BinaryFormatter(); memStream.Write(arrBytes, 0, arrBytes.Length); memStream.Seek(0, SeekOrigin.Begin); var obj = binForm.Deserialize(memStream); return obj; } } 

You can use this function with custom classes. You just need to add the [Serializable] attribute to your class to enable serialization.

+96
May 08 '12 at 16:47
source share

If you want serialized data to be really compact, you can write serialization methods yourself. Thus, you will have a minimum of overhead.

Example:

 public class MyClass { public int Id { get; set; } public string Name { get; set; } public byte[] Serialize() { using (MemoryStream m = new MemoryStream()) { using (BinaryWriter writer = new BinaryWriter(m)) { writer.Write(Id); writer.Write(Name); } return m.ToArray(); } } public static MyClass Desserialize(byte[] data) { MyClass result = new MyClass(); using (MemoryStream m = new MemoryStream(data)) { using (BinaryReader reader = new BinaryReader(m)) { result.Id = reader.ReadInt32(); result.Name = reader.ReadString(); } } return result; } } 
+28
Sep 18 '09 at 20:14
source share

Well, anything other than myObject to byte[] will never work unless you have an explicit conversion or if myObject is byte[] . You need a serialization structure. There are many, including Protocol Buffers , which is dear to me and dear. This is quite "meager and average" both in space and in time.

You will find that almost all serialization schemes have significant limitations on what you can serialize, however - the protocol buffers are larger than some due to cross-platform.

If you can provide more requirements, we can help you more, but it will never be as easy as casting ...

EDIT: just to answer this:

I need my binary to contain bytes of objects. Only bytes, no metadata. compacted object to object. So I will be implementing custom serialization.

Please keep in mind that bytes in your objects are often referenced ... so you will need to figure out what to do with them.

I suspect you will find that designing and implementing your own custom serialization scheme is more complex than you imagine.

I would personally recommend that if you need to do this only for a few specific types, you will not bother to come up with a general serialization scheme. Just implement the instance method and the static method in all the types you need:

 public void WriteTo(Stream stream) public static WhateverType ReadFrom(Stream stream) 

One thing to keep in mind: things get more complicated if you have inheritance. Without inheritance, if you know what type you start with, you do not need to include type information. Of course, there is also a versioning question - do you need to worry about compatibility with previous versions and switching to other versions of your types?

+22
Sep 18 '09 at 20:02
source share

You are really talking about serialization, which can take many forms. Since you need small and binary, protocol buffers can be a viable option, which also allows version portability and portability. Unlike BinaryFormatter , the protocol buffer protocol format does not include all type metadata; just very thin markers for identifying data.

There are several implementations in .NET; in particular

I humbly argue that protobuf-net (which I wrote) allows you to use .NET idioms with typical C # classes more ("regular" protocol buffers tend to require code generation); eg:

 [ProtoContract] public class Person { [ProtoMember(1)] public int Id {get;set;} [ProtoMember(2)] public string Name {get;set;} } .... Person person = new Person { Id = 123, Name = "abc" }; Serializer.Serialize(destStream, person); ... Person anotherPerson = Serializer.Deserialize<Person>(sourceStream); 
+9
Sep 18 '09 at 20:10
source share

I got a response from Crystalonics and turned them into extension methods. I hope someone else finds them useful:

 public static byte[] SerializeToByteArray(this object obj) { if (obj == null) { return null; } var bf = new BinaryFormatter(); using (var ms = new MemoryStream()) { bf.Serialize(ms, obj); return ms.ToArray(); } } public static T Deserialize<T>(this byte[] byteArray) where T : class { if (byteArray == null) { return null; } using (var memStream = new MemoryStream()) { var binForm = new BinaryFormatter(); memStream.Write(byteArray, 0, byteArray.Length); memStream.Seek(0, SeekOrigin.Begin); var obj = (T)binForm.Deserialize(memStream); return obj; } } 
+8
Jan 24 '14 at 21:21
source share

Take a look at Serialization , a method of "converting" an entire object to a stream of bytes. You can send it to the network or write to a file, and then restore it later.

+2
Sep 18 '09 at 20:03
source share

To access the objectโ€™s memory directly (to perform a โ€œcore dumpโ€), you need to go into unsafe code.

If you need something more compact than a BinaryWriter or a raw dam dump, you should write some custom serialization code that extracts critical information from the object and optimally packs it.

modify the postscript It's very easy to wrap the BinaryWriter approach in DeflateStream to compress data, which usually halves the size of the data.

+1
Sep 18 '09 at 20:03
source share

I found another way to convert an object to byte []. His solution:

 IEnumerable en = (IEnumerable) myObject; byte[] myBytes = en.OfType<byte>().ToArray(); 

Hello

+1
Jul 15 '14 at 8:00
source share

This worked for me:

 byte[] bfoo = (byte[])foo; 

foo is an object on which I am 100% sure that it is a byte array.

+1
Apr 24 '15 at 23:30
source share

I believe that what you are trying to do is impossible.
The garbage created by the BinaryFormatter is necessary to restore the object from the file after the program stops.
However, you can get object data, you just need to know the exact size (harder than it sounds):

 public static unsafe byte[] Binarize(object obj, int size) { var r = new byte[size]; var rf = __makeref(obj); var a = **(IntPtr**)(&rf); Marshal.Copy(a, r, 0, size); return res; } 

this can be restored via:

 public unsafe static dynamic ToObject(byte[] bytes) { var rf = __makeref(bytes); **(int**)(&rf) += 8; return GCHandle.Alloc(bytes).Target; } 

The reason the above methods do not work for serialization is because the first four bytes in the returned data correspond to RuntimeTypeHandle . RuntimeTypeHandle describes the layout / type of the object, but its value changes each time the program starts.

EDIT: this is stupid, do not do this โ†’ If you already know the type of deserialized object for a specific, you can switch these bytes for BitConvertes.GetBytes((int)typeof(yourtype).TypeHandle.Value) during deserialization.

+1
Jul 18 '15 at 16:59
source share

If you only had text or something like a repository, you could do something like: byte [] byteArray = Encoding.ASCII.GetBytes (myObject.text);

Otherwise, you will have to serialize a more attractive way.

0
Sep 18 '09 at 20:05
source share

I know this is an old post, but it still appears on top on google, so I wanted to add how I do it. I needed to transfer the image (as a byte []) in the object dictionary. The above suggestions did not work, because although my original array did this using ObjectToArray methods, the conversion changed the output to another.

after all, this simple process worked for me ...

  private object GetByteArray() { byte[] myReturn = new byte[] { 1, 2, 3, 4 }; return Convert.ToBase64String(myReturn); } private byte[] ConvertToByteArray(object myValues) { byte[] myReturn = Convert.FromBase64String(Convert.ToString(myValues)); return myReturn; } 
-2
Aug 26 '16 at 14:33
source share



All Articles