3

Is there a way to read binary data from file into an array like in C where I can pass a pointer of any type to the i/o functions? I am thinking of something like BinaryReader::ReadBytes(), but that returns a byte[] which I cannot cast to the desired array pointer type.

2
  • 1
    What exactly are you trying to read and what you want to do with that? If you're trying to read image, .NET got nice library for that. Commented Aug 16, 2011 at 12:16
  • Actually I want to read a short[] array, but BinaryReader only offers byte[] ReadBytes (...). I am coming from C/C++ where I can read (almost) everything bytewise by passing its address (reference) to the reading functions. Commented Aug 16, 2011 at 12:57

3 Answers 3

4

If you have a fixed size struct

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
struct MyFixedStruct
{
  //..
}

You can then read it in in one go using this:

public static T ReadStruct<T>(Stream stream)
{
    byte[] buffer = new byte[Marshal.SizeOf(typeof(T))];
    stream.Read(buffer, 0, Marshal.SizeOf(typeof(T)));
    GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
    T typedStruct = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
    handle.Free();
    return typedStruct;
}

This reads in a byte array covering the size of the struct and then marshals the byte array into the structure. You can use it like this:

MyFixedStruct fixedStruct =  ReadStruct<MyFixedStruct>(stream);

The struct may include array types as long as the array length is specified, i.e:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct MyFixedStruct
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
    public int[] someInts; // 5 int's
    //..
};

Edit:

I see you just want to read in a short array - In this case just read in the byte array and use Buffer.BlockCopy() to convert to the array you want:

byte[] someBytes = ..
short[] someShorts = new short[someBytes.Length/2];
Buffer.BlockCopy(someBytes, 0, someShorts, 0, someBytes.Length);

This is quite efficient, equivalent to a memcpy in C++ under the hood. The only other overhead you have of course is that the original byte array will be allocated and later garbage collected. This approach would work for any other primitive array type as well.

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

3 Comments

Ok, this might work, but (though that is not your fault) it is a ridiculous overhead.
@karx11erx: Updated the answer based on your comment that you just need a short array. This approach would work for any other primitive array type as well.
Alright, BlockCopy() ... I remember it now that you are mentioning it (I am just learning C# by porting a smaller C++ app of mine to C#, so I don't yet know all these things by heart, like I would in C++). Thank you for the explanation.
0

How about storing a serialized array of your struct in the file? You can build the array of structs easily. Not sure how to stream through the file though, as you would do in C.

1 Comment

I cannot just serialize the array because I am working with a legacy data format.
-1

How about using a Stream Class as it provides a generic view for sequence of bytes.

1 Comment

I don't necessarily want to read a byte array. I wrote that in my question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.