0

I am working on a project in c#. i want to read a binary file of 64k in length which is multiple of 16 bytes. each 16 byte is an event which has the form:

#pragma noalign(trace_record)
typedef struct trace_record
{
 BYTE char tr_id[2]; // 2 bytes
 WORD tr_task;       //2 bytes
 WORD tr_process;    //2 bytes
 WORD tr_varies;     //2 bytes
 KN_TIME_STRUCT tr_time; //8 bytes
} TRACE_RECORD;

i guess using Binaryreader class i can read the file but how to read it by multiples of 16 byte in this form. later i will extract some 16 byte traces for further processing. so I will be thankful for any help. please assume i am beginner in c# :)

5
  • 3
    If the file is in little endian, you can use BinaryReader.ReadUInt16 etc. to read individual fields. Don't try to read the whole record in a single memory copy. Commented Aug 1, 2014 at 10:18
  • Related answer: stackoverflow.com/questions/8704161/… Commented Aug 1, 2014 at 10:27
  • You may want to take a look at stackoverflow.com/questions/6918545/… and stackoverflow.com/questions/11909313/… Commented Aug 1, 2014 at 10:29
  • i think the best way to read/right this kind of data is to serialize it the the file Commented Aug 1, 2014 at 10:35
  • Create a memory mapped file, then unsafe cast to struct pointers. Same as fread in C. Commented Aug 1, 2014 at 11:37

1 Answer 1

1

The simplest working example is below. It can probably be improved though. If you have big-endian data i file, you can use a MiscUtil library for example.

public struct trace_record
{
    // you can create array here, but you will need to create in manually
    public byte tr_id_1; // 2 bytes
    public byte tr_id_2;

    public UInt16 tr_task;       //2 bytes
    public UInt16 tr_process;    //2 bytes
    public UInt16 tr_varies;     //2 bytes
    public UInt64 tr_time; //8 bytes
}

public static List<trace_record> ReadRecords(string fileName)
{
    var result = new List<trace_record>();

    // store FileStream to check current position
    using (FileStream s = File.OpenRead(fileName))
    // and BinareReader to read values
    using (BinaryReader r = new BinaryReader(s))
    {
        // stop when reached the file end
        while (s.Position < s.Length)
        {
            try
            {
                trace_record rec = new trace_record();
                // or read two bytes and use an array instead of two separate bytes.
                rec.tr_id_1 = r.ReadByte();
                rec.tr_id_2 = r.ReadByte();

                rec.tr_task = r.ReadUInt16();
                rec.tr_process = r.ReadUInt16();
                rec.tr_varies = r.ReadUInt16();
                rec.tr_time = r.ReadUInt64();

                result.Add(rec);
            }
            catch
            {
                // handle unexpected end of file somehow.
            }
        }

        return result;
    }
}

static void Main()
{
    var result = ReadRecords("d:\\in.txt");
    // get all records by condition
    var filtered = result.Where(r => r.tr_id_1 == 0x42);

    Console.ReadKey();
}

EDIT: it's probably better to use class instead of struct. See Why are mutable structs “evil”? Classes are more predictable, especially if you are new to C#. And result list will then store only references to objects.

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

2 Comments

Thanks. It helped me alot. Now how can i access a particular 16 byte record whose first byte ( tr_id_1) is a character 'B' ?
I've updated initial answer to search for all such records using Linq. This may be a bit slow if you have a lot of records. Consider using for loop or some kind of caching/indexing during reading records if you know search conditions at the moment of reading file. You can even store data in a database like SQLite.

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.