为什么 BinaryReader.ReadUInt32() 会反转位模式?
我正在尝试使用 BinaryReader 类读取二进制文件,并且我需要将其作为 UInt32 块读取,然后进行一些位移等操作。
但是,由于某种原因,当我使用 ReadUInt32 方法时,位顺序会颠倒。
例如,如果我有一个文件,其中前四个字节在十六进制中看起来像这样,0x12345678
,那么它们在被 ReadUInt32 读取后最终会像这样:0x78563412
。
如果我使用 ReadBytes(4) 方法,我会得到预期的数组:
[0x00000000] 0x12 byte
[0x00000001] 0x34 byte
[0x00000002] 0x56 byte
[0x00000003] 0x78 byte
这是为什么? 这就是 .net 在内存中表示 uint 的方式吗? 不同平台上的情况是否相同(我运行的是 64 位 Windows 7、.net 3.5 sp1)?
I am trying to read a binary file with the BinaryReader class, and I need to read it in as blocks of UInt32, and then do some bit shifting etc. afterwords.
But, for some reason bit order is reversed when I use the ReadUInt32 method.
If I for example have a file where the first four bytes looks like this in hex, 0x12345678
, they end up like this after being read by ReadUInt32: 0x78563412
.
If I use the ReadBytes(4) method, I get the expected array:
[0x00000000] 0x12 byte
[0x00000001] 0x34 byte
[0x00000002] 0x56 byte
[0x00000003] 0x78 byte
Why is this? Is it just the way .net represents uints in memory? Is it the same across the different platforms (I am running 64bit Windows 7, .net 3.5 sp1)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
是的,这与计算机硬件在内存中存储单位的方式有关。 尽管大多数台式计算机应该是相同的,但在不同的平台上它可能会有所不同。
这称为字节顺序 - 请参阅此处的维基百科:
http://en.wikipedia.org/wiki/Endian
Yes, this has to do with how your computer hardware stores uints in memory. It can be different across different platforms, although most desktop computers should be the same.
This is called endianness -- see wikipedia here:
http://en.wikipedia.org/wiki/Endian
这似乎是一个 endianness 问题。 文档说 ReadUint32 以小端方式读取因此第一个字节是最低有效的,因此它位于最低的内存位置。 你的作者一定是大端字节序吗?
BinaryWriter.Write(UInt32)
说它写入 也是小端字节序。 你的二进制数据源不是BinaryWriter吗?基本上,修复它需要做的是:
将最低有效字节上移 24 位,将第 2 个 LSB 上移 8 位,将第 3 个 LSB 下移 8 位,将第 4 个 LSB(MSB)下移 24 位。 多个库都介绍了这样做的方法。
也许使用 BitConverter 会更清楚一些:
This seems to be an endianness issue. The docs say ReadUint32 reads in little-endian so the first byte is the least-significant so it goes to the lowest memory location. Your writer must be big-endian?
BinaryWriter.Write(UInt32)
says it writes little-endian too. Is your binary data source not BinaryWriter?Essentially what you need to do to fix it is this:
This shifts the least-significant byte up 24 bits, the 2nd LSB up 8 bits, the 3rd LSB down 8 bits, and the 4th LSB (the MSB) down 24 bits. Doing this is covered in several libraries.
Perhaps using
BitConverter
would be a bit more clear:查看 Jon Skeet 的 MiscUtil 库中的 Endian* 类,例如 EndianBinaryReader 和 EndianBitConverter。
http://www.yoda.arachsys.com/csharp/miscutil/
Look into Jon Skeet's MiscUtil library for the Endian* classes, like EndianBinaryReader and EndianBitConverter.
http://www.yoda.arachsys.com/csharp/miscutil/
Jon Skeet 编写了一个具有可配置字节序的 BitConverter。 您可能会发现它很有用。
http://www.yoda.arachsys.com/csharp/miscutil/
Jon Skeet's written a BitConverter with configurable endian-ness. You might find it useful.
http://www.yoda.arachsys.com/csharp/miscutil/
这是平台 Endianess 的问题。 当您从流中读取数据时,您必须根据其写入的字节顺序来读取它。 如果您在 .Net 中创建数据,则 .Net 将正确读取它。
This is an issue of platform Endianess. When you read data from a stream you must read it accordingly to the endianess it was written as. If you created the data in .Net, then .Net will read it correctly.
阅读通用 BinaryReader 和 BinaryWriter 扩展,这是处理非托管泛型转换的好方法方式。
对于 VB.NET(仅安全代码,也可以在 C# 中实现)使用以下内容:
Imports System.IO
导入 System.Runtime.CompilerServices
导入 System.Runtime.InteropServices
您现在可以为
BitConverter
,用于BinaryWriter
等Read Generic BinaryReader and BinaryWriter Extensions, a great way to handle generic casting the unmanaged way.
For VB.NET (safe code only, can also be achieved in C#) use the following:
Imports System.IO
Imports System.Runtime.CompilerServices
Imports System.Runtime.InteropServices
You can now implement the same functionality for
BitConverter
, forBinaryWriter
etc.