我可以使用 C# 序列化来读取自定义格式的二进制文件吗?

Posted

技术标签:

【中文标题】我可以使用 C# 序列化来读取自定义格式的二进制文件吗?【英文标题】:Can I use C# Serialization to read a binary file in custom format? 【发布时间】:2010-11-11 12:08:55 【问题描述】:

我有一个自定义二进制文件,我想将其读入我的 C# 程序。

有几种不同的格式,有些是 MSB 在前,有些是 LSB 在前,有些变量的顺序不同。

目前,我有一个类可以读取正确数量的字节,一次一个。

它非常慢,所以我希望尽我所能提高性能。

序列化可能会表现得更好吗?如果是这样,这可能与我所描述的场景有关吗?是否可以为 big/little-endian 格式自定义 BinaryFormatter?

谢谢。

【问题讨论】:

【参考方案1】:

BinaryFormatter 无法做到这一点 - 它会期望对象周围有额外的元数据/填充。您必须手动从Stream 或类似地通过二进制阅读器读取。

在完成了一些非常相似的代码之后,我会编写自己的阅读器,它位于流的顶部,方法如下:ReadInt32LittleEndianReadInt32BigEndian(等你需要的一切)-并使用 shift (<< />>) 来组装字节。但重要的是我会使用后备缓冲区来减少对底层流的调用量(即使使用缓冲区,这可能会慢得令人无法接受)。

让我向您推荐一些来自 protobuf-net 的代码,它可以做到这一点……特别是 ProtoReader,举个例子:

    /// <summary>
    /// Reads an unsigned 32-bit integer from the stream; supported wire-types: Variant, Fixed32, Fixed64
    /// </summary>
    public uint ReadUInt32()
    
        switch (wireType)
        
            case WireType.Variant:
                return ReadUInt32Variant(false);
            case WireType.Fixed32:
                if (available < 4) Ensure(4, true);
                position += 4;
                available -= 4;
                return ((uint)ioBuffer[ioIndex++])
                    | (((uint)ioBuffer[ioIndex++]) << 8)
                    | (((uint)ioBuffer[ioIndex++]) << 16)
                    | (((uint)ioBuffer[ioIndex++]) << 24);
            case WireType.Fixed64:
                ulong val = ReadUInt64();
                checked  return (uint)val; 
            default:
                throw CreateException();
        
    

(这里wireType广泛充当字节序等指示符,但这并不重要)

查看Fixed32 实现:

Ensure 确保我们的后备缓冲区中至少还有 4 个字节(如果需要,可以获取更多字节) 我们增加了一些计数器,以便跟踪我们在逻辑缓冲区中的位置 我们从缓冲区中读取数据

如果您有适合您格式的阅读器,反序列化应该会容易得多。

【讨论】:

【参考方案2】:

不,它不会工作。可以,但是转换的开销可能会影响性能。

【讨论】:

以上是关于我可以使用 C# 序列化来读取自定义格式的二进制文件吗?的主要内容,如果未能解决你的问题,请参考以下文章

对十进制数使用自定义字符串格式c#

学习笔记Hadoop—— MapReduce编程进阶

学习笔记Hadoop(十五)—— MapReduce编程进阶

C# XML 反序列化为一张表中的 DataSet

使用 C# 反序列化 JSON

c# richtextbox : 如果把richtextbox中的文字图片保存到数据库(access)中。