Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Packing a class into a byte array - would [Serializable] do the trick?

Packing a class into a byte array - would [Serializable] do the trick?

Scheduled Pinned Locked Moved C#
data-structurestutorialquestion
10 Posts 2 Posters 1 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    Dewald
    wrote on last edited by
    #1

    I'm looking for a way to represent an instantiated class as a byt array (and populate an instantiated class frm a byte array. I was hoping that [Serializable] would be the magic bullet but it seems I was wrong - or do I just not understand how to use [Serializable] properly? Let's say I have:

    public class myClass
    {
    public byte myByte1;
    public byte myByte2;
    public ushort myUshort1;
    public ushort myUshort2;

    public myClass()
    {
    this.myByte1 = 0x01;
    this.myByte2 = 0x02;
    this.myUshort1 = 0x0304;
    this.myUshort2 = 0x0506;
    }
    }

    Now, if I instantiate this class with myClass myInstance = new myClass() the member variales will hold the values as defined by the constructor. I'd like to be able to view the contents of the class as an array of bytes (ie. {0x01, 0x02, 0x03, 0x04, 0x05, 0x06}). So I was thinking that if the class is serializable and I write the seraialized stream to a byte array (or write a byte array to the associated stream) I'd be able to pull it off, something like this:

    MemoryStream memStream = new MemoryStream();
    BinaryFormatter binFormatter = new BinaryFormatter();
    binFormatter.Serialize(memStream, myInstance);
    byte[] myBytes = memStream.ToArray();

    But myBytes is 183 bytes in size (as opposed to the expected 6 bytes) once this is finished and the contents of myBytes makes no sense to me whatsoever. Am I on completely the wrong track here or is there hope?

    A 1 Reply Last reply
    0
    • D Dewald

      I'm looking for a way to represent an instantiated class as a byt array (and populate an instantiated class frm a byte array. I was hoping that [Serializable] would be the magic bullet but it seems I was wrong - or do I just not understand how to use [Serializable] properly? Let's say I have:

      public class myClass
      {
      public byte myByte1;
      public byte myByte2;
      public ushort myUshort1;
      public ushort myUshort2;

      public myClass()
      {
      this.myByte1 = 0x01;
      this.myByte2 = 0x02;
      this.myUshort1 = 0x0304;
      this.myUshort2 = 0x0506;
      }
      }

      Now, if I instantiate this class with myClass myInstance = new myClass() the member variales will hold the values as defined by the constructor. I'd like to be able to view the contents of the class as an array of bytes (ie. {0x01, 0x02, 0x03, 0x04, 0x05, 0x06}). So I was thinking that if the class is serializable and I write the seraialized stream to a byte array (or write a byte array to the associated stream) I'd be able to pull it off, something like this:

      MemoryStream memStream = new MemoryStream();
      BinaryFormatter binFormatter = new BinaryFormatter();
      binFormatter.Serialize(memStream, myInstance);
      byte[] myBytes = memStream.ToArray();

      But myBytes is 183 bytes in size (as opposed to the expected 6 bytes) once this is finished and the contents of myBytes makes no sense to me whatsoever. Am I on completely the wrong track here or is there hope?

      A Offline
      A Offline
      AikinX
      wrote on last edited by
      #2

      Here are many additional information is added with serialization like assembly name, version, class name, structure, ........ All this information is necessary to deserialize this object

      D 1 Reply Last reply
      0
      • A AikinX

        Here are many additional information is added with serialization like assembly name, version, class name, structure, ........ All this information is necessary to deserialize this object

        D Offline
        D Offline
        Dewald
        wrote on last edited by
        #3

        Aha, that makes sense. So does that mean that [Serializable] would not be the proper route then? Would you have any other suggestions?

        A 1 Reply Last reply
        0
        • D Dewald

          Aha, that makes sense. So does that mean that [Serializable] would not be the proper route then? Would you have any other suggestions?

          A Offline
          A Offline
          AikinX
          wrote on last edited by
          #4

          Dewald wrote:

          Aha, that makes sense. So does that mean that [Serializable] would not be the proper route then?

          Yes, if the array size is not critical. If critical you have to realize you own convertion like: public class myClass { public byte myByte1; public byte myByte2; public ushort myUshort1; public ushort myUshort2; public myClass() { } public static byte[] ToByteArray(myClass value) { byte[] result = new byte[6]; result[0] = value.myByte1; result[1] = value.myByte2; unchecked { result[2] = (byte)(value.myUshort1 / 256); result[3] = (byte)(value.myUshort1 - result[2] * 256); result[4] = (byte)(value.myUshort2 / 256); result[5] = (byte)(value.myUshort2 - result[4] * 256); } return result; } public static myClass FromByteArray(byte[] array) { myClass result = new myClass(); result.myByte1 = array[0]; result.myByte2 = array[1]; result.myUshort1 = (ushort)(array[2] * 256 + array[3]); result.myUshort2 = (ushort)(array[4] * 256 + array[5]); return result; } } P.S. usort is 16-bit type so we need to store it into two bytes.

          D 1 Reply Last reply
          0
          • A AikinX

            Dewald wrote:

            Aha, that makes sense. So does that mean that [Serializable] would not be the proper route then?

            Yes, if the array size is not critical. If critical you have to realize you own convertion like: public class myClass { public byte myByte1; public byte myByte2; public ushort myUshort1; public ushort myUshort2; public myClass() { } public static byte[] ToByteArray(myClass value) { byte[] result = new byte[6]; result[0] = value.myByte1; result[1] = value.myByte2; unchecked { result[2] = (byte)(value.myUshort1 / 256); result[3] = (byte)(value.myUshort1 - result[2] * 256); result[4] = (byte)(value.myUshort2 / 256); result[5] = (byte)(value.myUshort2 - result[4] * 256); } return result; } public static myClass FromByteArray(byte[] array) { myClass result = new myClass(); result.myByte1 = array[0]; result.myByte2 = array[1]; result.myUshort1 = (ushort)(array[2] * 256 + array[3]); result.myUshort2 = (ushort)(array[4] * 256 + array[5]); return result; } } P.S. usort is 16-bit type so we need to store it into two bytes.

            D Offline
            D Offline
            Dewald
            wrote on last edited by
            #5

            Yip, this is exactly what I've been doing up until now but I was just hoping that there wuld be a more elegant sollution. The thing is that I have various classes that I'd like to be able to pack into byte arrays (basically the classes are just messages that I need to transmit and receive over a TCP socket). I was hoping that I could write a base class that provides a method of packing the class into an array and then derrive all the other classes from that class. That way I wouldn't have to implement a huge amount of tedious code to pack every individual member variable of the class into the array.

            A 2 Replies Last reply
            0
            • D Dewald

              Yip, this is exactly what I've been doing up until now but I was just hoping that there wuld be a more elegant sollution. The thing is that I have various classes that I'd like to be able to pack into byte arrays (basically the classes are just messages that I need to transmit and receive over a TCP socket). I was hoping that I could write a base class that provides a method of packing the class into an array and then derrive all the other classes from that class. That way I wouldn't have to implement a huge amount of tedious code to pack every individual member variable of the class into the array.

              A Offline
              A Offline
              AikinX
              wrote on last edited by
              #6

              Sorry, I have no ideas how to help you this case. If you message is more than 6 byte the volume of valuable information will be more. Also you may try to zip it by DeflateStream....

              1 Reply Last reply
              0
              • D Dewald

                Yip, this is exactly what I've been doing up until now but I was just hoping that there wuld be a more elegant sollution. The thing is that I have various classes that I'd like to be able to pack into byte arrays (basically the classes are just messages that I need to transmit and receive over a TCP socket). I was hoping that I could write a base class that provides a method of packing the class into an array and then derrive all the other classes from that class. That way I wouldn't have to implement a huge amount of tedious code to pack every individual member variable of the class into the array.

                A Offline
                A Offline
                AikinX
                wrote on last edited by
                #7

                Dewald, last night I got an idea: in unmanaged C++ we just need to look at the object as byte array: // Some & and * have to be added to next code to say we are working with references MyClass myCl = new MyClass(); byte[] array = meCl; // this operation is allowed fo references // coping this array to new one or sending it as is through TCP socet But in .Net we haven't references (that is very good, in my opinion), but we have some classes that allow to work with objects by references way. One of them is System.Runtime.InteropServices.Marshal I have never worked with, just herad about it. I have being looking through this and find some pairs of static methods wich can help you (I guess): To get IntPTR from your object: public static extern void StructureToPtr(object structure, IntPtr ptr, bool fDeleteOld); public static object PtrToStructure(IntPtr ptr, Type structureType) To copy to byte array: public static void Copy(IntPtr source, byte[] destination, int startIndex, int length); public static void Copy(byte[] source, int startIndex, IntPtr destination, int length) Or public static extern byte ReadByte(object ptr, int ofs); public static extern void WriteByte(IntPtr ptr, int ofs, byte val); Regards. P.S. IntPtr (intPointer) is Net analog of C++ pointers -- modified at 2:48 Saturday 9th June, 2007

                A 1 Reply Last reply
                0
                • A AikinX

                  Dewald, last night I got an idea: in unmanaged C++ we just need to look at the object as byte array: // Some & and * have to be added to next code to say we are working with references MyClass myCl = new MyClass(); byte[] array = meCl; // this operation is allowed fo references // coping this array to new one or sending it as is through TCP socet But in .Net we haven't references (that is very good, in my opinion), but we have some classes that allow to work with objects by references way. One of them is System.Runtime.InteropServices.Marshal I have never worked with, just herad about it. I have being looking through this and find some pairs of static methods wich can help you (I guess): To get IntPTR from your object: public static extern void StructureToPtr(object structure, IntPtr ptr, bool fDeleteOld); public static object PtrToStructure(IntPtr ptr, Type structureType) To copy to byte array: public static void Copy(IntPtr source, byte[] destination, int startIndex, int length); public static void Copy(byte[] source, int startIndex, IntPtr destination, int length) Or public static extern byte ReadByte(object ptr, int ofs); public static extern void WriteByte(IntPtr ptr, int ofs, byte val); Regards. P.S. IntPtr (intPointer) is Net analog of C++ pointers -- modified at 2:48 Saturday 9th June, 2007

                  A Offline
                  A Offline
                  AikinX
                  wrote on last edited by
                  #8

                  I've done the copying for value object (structure). One thing I can't make is to get a pointer (IntPtr) from reference object (class). public struct myStuct { public byte myByte1; public byte myByte2; public ushort myUshort1; public ushort myUshort2; private const int MY_SIZE = 6; public static byte[] ToByteArray(myStuct source) { // Allocating an unmanagement memory for marshaling IntPtr pointer = System.Runtime.InteropServices.Marshal.AllocHGlobal(MY_SIZE); // Copying instance to allocated memory System.Runtime.InteropServices.Marshal.StructureToPtr(source, pointer, false); byte[] result = new byte[MY_SIZE]; // Coping filled memory to byte array System.Runtime.InteropServices.Marshal.Copy(pointer, result, 0, MY_SIZE); return result; } public static myStuct FromByteArray(byte[] source) { if (source == null) throw new ArgumentNullException("Source array can not be null"); if (source.Length != MY_SIZE) throw new ArgumentException("Source array's size has to be " + MY_SIZE + " bytes"); // Allocating an unmanagement memory for marshaling IntPtr pointer = System.Runtime.InteropServices.Marshal.AllocHGlobal(MY_SIZE); // Coping byte array to allocated memory System.Runtime.InteropServices.Marshal.Copy(source, 0, pointer, MY_SIZE); // Creating instance from unmanagment memory myStuct result = (myStuct)System.Runtime.InteropServices.Marshal.PtrToStructure(pointer, typeof(myStuct)); return result; } }

                  D 1 Reply Last reply
                  0
                  • A AikinX

                    I've done the copying for value object (structure). One thing I can't make is to get a pointer (IntPtr) from reference object (class). public struct myStuct { public byte myByte1; public byte myByte2; public ushort myUshort1; public ushort myUshort2; private const int MY_SIZE = 6; public static byte[] ToByteArray(myStuct source) { // Allocating an unmanagement memory for marshaling IntPtr pointer = System.Runtime.InteropServices.Marshal.AllocHGlobal(MY_SIZE); // Copying instance to allocated memory System.Runtime.InteropServices.Marshal.StructureToPtr(source, pointer, false); byte[] result = new byte[MY_SIZE]; // Coping filled memory to byte array System.Runtime.InteropServices.Marshal.Copy(pointer, result, 0, MY_SIZE); return result; } public static myStuct FromByteArray(byte[] source) { if (source == null) throw new ArgumentNullException("Source array can not be null"); if (source.Length != MY_SIZE) throw new ArgumentException("Source array's size has to be " + MY_SIZE + " bytes"); // Allocating an unmanagement memory for marshaling IntPtr pointer = System.Runtime.InteropServices.Marshal.AllocHGlobal(MY_SIZE); // Coping byte array to allocated memory System.Runtime.InteropServices.Marshal.Copy(source, 0, pointer, MY_SIZE); // Creating instance from unmanagment memory myStuct result = (myStuct)System.Runtime.InteropServices.Marshal.PtrToStructure(pointer, typeof(myStuct)); return result; } }

                    D Offline
                    D Offline
                    Dewald
                    wrote on last edited by
                    #9

                    Thanks for all the effort AikinX, I also discovered this approach but, like you, I couldn't get it to work for classes. I never even bothered to try using it for structures (silly of me) and this will do nicely. It is a bit of a pity that I have to resort to unmanage code. I would have prefered if there was a way that I could do this without having to use pointers, and there probably is which is still elluding me. Either way, for now, this will do. Thanks again.

                    A 1 Reply Last reply
                    0
                    • D Dewald

                      Thanks for all the effort AikinX, I also discovered this approach but, like you, I couldn't get it to work for classes. I never even bothered to try using it for structures (silly of me) and this will do nicely. It is a bit of a pity that I have to resort to unmanage code. I would have prefered if there was a way that I could do this without having to use pointers, and there probably is which is still elluding me. Either way, for now, this will do. Thanks again.

                      A Offline
                      A Offline
                      AikinX
                      wrote on last edited by
                      #10

                      I don't like pointers too. But it is the only way to do the serialization in general for any class. So, I think you have to choose built-in serialization or do it manually. Best Regards

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups