C# 二进制文件使用C读取预定义的字节数/字节#

C# 二进制文件使用C读取预定义的字节数/字节#,c#,character-encoding,binaryfiles,C#,Character Encoding,Binaryfiles,场景 我有一个二进制文件,它是某个系统的输出。供应商向我们提供了文件编码的说明。它非常复杂,因为编码遵循某种方法。例如,第一个字节是ISO编码的,我们需要首先对其进行解码,如果该值与提供的列表匹配,则它具有某种意义。接下来的15个字节也是ISO编码的,我们需要对其进行解码和比较。类似地,在某些位置之后,很少有字节是二进制编码的。。诸如此类 迄今为止的行动 我将使用C#WinForm应用程序。到目前为止,我已经查看了各种文档,它们都指向FileStream/BinaryReader的组合,因为我的

场景 我有一个二进制文件,它是某个系统的输出。供应商向我们提供了文件编码的说明。它非常复杂,因为编码遵循某种方法。例如,第一个字节是ISO编码的,我们需要首先对其进行解码,如果该值与提供的列表匹配,则它具有某种意义。接下来的15个字节也是ISO编码的,我们需要对其进行解码和比较。类似地,在某些位置之后,很少有字节是二进制编码的。。诸如此类

迄今为止的行动 我将使用C#WinForm应用程序。到目前为止,我已经查看了各种文档,它们都指向FileStream/BinaryReader的组合,因为我的文件大小在1G到1.8G之间。我也不能将整个文件放在一个字节[]中

问题
我面临着逐字节读取文件的问题。根据上面的场景,首先我只需要读取1个字节,然后是15个字节,然后是10个字节,依此类推。如何做到这一点。提前感谢你的帮助

BinaryReader.ReadBytes方法
将当前流中指定数量的字节读取到字节数组中,并将当前位置前进该数量的字节


BinaryReader是一个不错的选择,因为它使用的是流,所以内存使用率很低。

现在,您可以执行以下操作:

internal struct MyHeader
{
    public byte FirstByte;
    // etc
}

internal class MyFormat
{
    private readonly string _fileName;

    private MyFormat(string fileName)
    {
        _fileName = fileName;
    }


    public MyHeader Header { get; private set; }

    public string FileName
    {
        get { return _fileName; }
    }


    public static MyFormat FromFileName(string fileName)
    {
        if (fileName == null) throw new ArgumentNullException("fileName");

        // read the header of your file
        var header = new MyHeader();
        using (var reader = new BinaryReader(File.OpenRead(fileName)))
        {
            byte b1 = reader.ReadByte();
            if (b1 != 0xAA)
            {
                // return null or throw an exception
            }
            header.FirstByte = b1;

            // you can also read block of bytes with a BinaryReader
            var readBytes = reader.ReadBytes(10);

            // etc ... whenever something's wrong return null or throw an exception
        }

        // when you're done reading your header create and return the object
        var myFormat = new MyFormat(fileName);
        myFormat.Header = header;

        // the rest of the object is delivered only when needed, see method below

        return myFormat;
    }

    public object GetBigContent()
    {
        var content = new object();
        // use FileName and Header property to get your big content and return it
        // again, use a BinaryReader with 'using' statement here
        return content;
    }
}
解释 调用
MyFormat.FromFileName
在其中创建以下对象之一:

  • 每当发生错误时,您都会分析标头,并返回null或引发异常
  • 一旦你的头被解析,你就创建了这个对象并返回它,就这样了
由于您只是读取标题,请提供一种读取文件中较大部分的方法。

伪示例:

无论何时需要阅读大部分内容,都可以使用
GetBigContent
或任何您想调用的名称

在该方法中使用
标题
文件名
,您将获得按需从该文件返回内容所需的一切

通过这种方式,

  • 您只需解析一个有效对象的头,就可以快速返回该对象
  • 您在第一次呼叫时不会消耗1.8Gb
  • 您只按需返回用户需要的内容
对于编码相关的内容,
encoding
类可能会对您有所帮助:

Stream和BinaryReader都有读取单个字节和读取多个字节的方法(Stream:ReadByte/Read,BinaryReader:ReadByte/ReadBytes)——它们都不要求您将整个文件读入一个字节[]。OP可能知道,他正在寻找一种解决问题的通用方法。“我只需要读取1个字节,然后是15个字节,然后是10个字节,依此类推。我想如果我的答案太长的话,他也不能把整个1.8Gb的文件放在一个数组中。
internal struct MyHeader
{
    public byte FirstByte;
    // etc
}

internal class MyFormat
{
    private readonly string _fileName;

    private MyFormat(string fileName)
    {
        _fileName = fileName;
    }


    public MyHeader Header { get; private set; }

    public string FileName
    {
        get { return _fileName; }
    }


    public static MyFormat FromFileName(string fileName)
    {
        if (fileName == null) throw new ArgumentNullException("fileName");

        // read the header of your file
        var header = new MyHeader();
        using (var reader = new BinaryReader(File.OpenRead(fileName)))
        {
            byte b1 = reader.ReadByte();
            if (b1 != 0xAA)
            {
                // return null or throw an exception
            }
            header.FirstByte = b1;

            // you can also read block of bytes with a BinaryReader
            var readBytes = reader.ReadBytes(10);

            // etc ... whenever something's wrong return null or throw an exception
        }

        // when you're done reading your header create and return the object
        var myFormat = new MyFormat(fileName);
        myFormat.Header = header;

        // the rest of the object is delivered only when needed, see method below

        return myFormat;
    }

    public object GetBigContent()
    {
        var content = new object();
        // use FileName and Header property to get your big content and return it
        // again, use a BinaryReader with 'using' statement here
        return content;
    }
}