【问题标题】:how to read binary file as a struct in c#?如何在c#中将二进制文件作为结构读取?
【发布时间】:2014-08-01 10:16:23
【问题描述】:

我正在使用 C# 开发一个项目。我想读取一个长度为 64k 的二进制文件,它是 16 字节的倍数。每 16 个字节是一个事件,其形式如下:

#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;

我猜使用 Binaryreader 类我可以读取文件,但如何以这种形式读取 16 字节的倍数。稍后我将提取一些 16 字节的痕迹以进行进一步处理。所以我会感谢任何帮助。请假设我是 C# 的初学者 :)

【问题讨论】:

标签: c# struct


【解决方案1】:

最简单的工作示例如下。不过可能还可以改进。如果你有大端数据 i 文件,你可以使用 MiscUtil 库为例。

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();
}

编辑:最好使用class 而不是struct。请参阅Why are mutable structs “evil”? 类更容易预测,尤其是如果您是 C# 新手。然后结果列表将只存储对对象的引用。

【讨论】:

  • 谢谢。这对我帮助很大。现在我如何访问第一个字节 (tr_id_1) 是字符“B”的特定 16 字节记录?
  • 我已更新初始答案以使用 Linq 搜索所有此类记录。如果您有很多记录,这可能会有点慢。如果您在读取文件时知道搜索条件,请考虑在读取记录期间使用for 循环或某种缓存/索引。您甚至可以将数据存储在 SQLite 等数据库中。
猜你喜欢
  • 2011-05-08
  • 1970-01-01
  • 2017-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-16
相关资源
最近更新 更多