我可以使用 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
或类似地通过二进制阅读器读取。
在完成了一些非常相似的代码之后,我会编写自己的阅读器,它位于流的顶部,方法如下:ReadInt32LittleEndian
、ReadInt32BigEndian
(等你需要的一切)-并使用 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# 序列化来读取自定义格式的二进制文件吗?的主要内容,如果未能解决你的问题,请参考以下文章