gonzobrains
gonzobrains

Reputation: 8034

How to write file header using FileStream in C#

I am creating my own video file format and would like to write out a file header and frame headers.

At the moment I just have placeholders defined as such:

byte[] fileHeader = new byte[FILE_HEADER_SIZE * sizeof(int)];
byte[] frameHeader = new byte[FRAME_HEADER_SIZE * sizeof(int)];

I write them out using the following for the file header:

fsVideoWriter.Write(fileHeader, 0, FILE_HEADER_SIZE);

and this for the frame headers:

fsVideoWriter.Write(frameHeader, 0, FRAME_HEADER_SIZE);

Now that I actually need to make proper use of these headers, I'm not sure if this would be the most convenient way to write them, as I am not sure if it will be easy to read in the individual fields I need into separate variables from the headers.

I thought about doing something like the following:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct FileHeader
{
    public int x;
    public int y;
    public int z;
            // etc. etc.
}

I would like to define it in such a way that I can upgrade easily as the file format evolves, (i.e. including a version number). Is this the recommended way to define a file/frame header? If so, how should I read/write it using the .NET FileStream class? If this is not the recommended way, please suggest the proper way to do this, as maybe someone has already created a generic video file-related class that handles this sort of thing?

Upvotes: 3

Views: 5399

Answers (2)

gonzobrains
gonzobrains

Reputation: 8034

I settled upon the following solution:

Writing out file header

public static bool WriteFileHeader(FileStream fileStream, FileHeader fileHeader)
{
    try
    {
        byte[] buffer = new byte[FILE_HEADER_SIZE];

        GCHandle gch = GCHandle.Alloc(buffer, GCHandleType.Pinned);
        Marshal.StructureToPtr(fileHeader, gch.AddrOfPinnedObject(), false);
        gch.Free();

        fileStream.Seek(0, SeekOrigin.Begin);                
        fileStream.Write(buffer, 0, FILE_HEADER_SIZE);

        return true;
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

Reading in file header

public static bool ReadFileHeader(FileStream fileStream, out FileHeader fileHeader)
{
    try
    {
        fileHeader = new FileHeader();

        byte[] buffer = new byte[FILE_HEADER_SIZE];

        fileStream.Seek(0, SeekOrigin.Begin);
        fileStream.Read(buffer, 0, FILE_HEADER_SIZE);

        GCHandle gch = GCHandle.Alloc(buffer, GCHandleType.Pinned);
        Marshal.PtrToStructure(gch.AddrOfPinnedObject(), fileHeader);

        gch.Free();

        // test for valid data
        boolean isSuccessful = IsValidHeader(fileHeader);

        return isSuccessful;

    }
    catch (Exception ex)
    {
        throw ex;
    }

}

I used a similar approach for the frame headers as well. The idea is basically to make use of byte buffers and Marshal.

Upvotes: 1

Naruil
Naruil

Reputation: 2310

You may want to try the BinaryFormatter Class. But it is more or less a black box. If you need precise control of your file format, you can write your own Formatter and use it to serialize your header object.

Upvotes: 0

Related Questions