0

I am trying to serialize a structure to disk as raw bytes. This is a (simplified)version of it.

[StructLayout(LayoutKind.Sequential, Pack = 1)] public class TestData :BaseStructure { public byte[] bytes = new byte[]{65,66,67}; // this doesn't write ABC as expected } 

A write function uses ConvertStructureToBytes method to convert this to a byte array and a binary writer then writes it.

 public void Write(BaseStructure baseStructure) { binaryWriter.Write(ConvertStructureToBytes(baseStructure)); } 

The ConvertStructureToBytes section

 public byte[] ConvertStructureToBytes(BaseStructure baseStructure) { int len = Marshal.SizeOf(baseStructure); byte[] arr = new byte[len]; IntPtr ptr = Marshal.AllocHGlobal(len); Marshal.StructureToPtr(baseStructure, ptr,false); Marshal.Copy(ptr, arr, 0, len); Marshal.FreeHGlobal(ptr); return arr; } 

If I replace the bytes line to

public byte byte = 65; // This now writes an A , as expected 

I have tried

public byte[] bytes = Encoding.ASCII.GetBytes("ABC"); //doesn't work either 

This probably has something to do with the ConvertStructureToBytes function , it isn't treating the byte array as it should.

What do I need to do to be able to write 'ABC' successfully?

2
  • I have edited your title. Please see, "Should questions include “tags” in their titles?", where the consensus is "no, they should not". Commented Sep 12, 2014 at 21:04
  • What is BaseStructure? Your TestData class inherits from it, but you are not serialising a TestData instance but a BaseStructure instance, which is not aware of the data declared in the TestData class. Commented Sep 12, 2014 at 21:10

3 Answers 3

3

Several problems. First your structure declaration is not correct, you have to in-line the array so it no longer a pointer:

[StructLayout(LayoutKind.Sequential, Pack = 1)] public class TestData { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] bytes = new byte[] { 65, 66, 67 }; } 

Then your ConvertStructureToBytes() method is not correct, it is only ever going to marshal BaseStructure. You need to make it generic:

public static byte[] ConvertStructureToBytes<T>(T baseStructure) { // rest the same... } 

Do note the kind of trouble you can get into with this approach, it most certainly is not a universal way to marshal data. Only very specific classes can be serialized this way. That [MarshalAs] attribute is of course very painful to maintain. You might as well use binary serialization.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, this WORKS! Yay... I am actually writing raw bytes for ISO9660 structure and the classes involved are directories,files and path tables, all predefined and the fields, such as bytes above wont' change. So I think this solution works fine for me :)
Okay, a fixed set of structure declarations is fine. Please close your question.
1

Change the class definition to this and try it:

StructLayout(LayoutKind.Sequential, Pack = 1)] public class TestData :BaseStructure { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] bytes = new byte[]{65,66,67}; } 

Comments

0

Try this:

byte[] bytes = Encoding.ASCII.GetBytes("ABC").ToArray(); 

Or, after I tested that. Maybe you mean this:

bytes = new byte[] { 65, 66, 67 }; string test = Encoding.UTF8.GetString(bytes).ToString(); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.