如何使用 bitConverter.ToInt32 方法从 C# 中的大端数据获取小端数据?
我正在 C# 中制作应用程序,它有一个包含十六进制值的字节数组。
我获取的数据为大端字节序,但我希望它为小端字节序,并且我正在使用 Bitconverter.toInt32 方法将该值转换为整数。
我的问题是,在转换值之前,我必须将 4 字节数据从源字节数组复制到临时数组中,然后反转该临时字节数组。
我无法反转源数组,因为它还包含其他数据。
因此我的应用程序变得很慢。
在代码中,我有一个字节源数组作为 waveData[]
,其中包含大量数据。
byte[] tempForTimestamp=new byte[4];
tempForTimestamp[0] = waveData[290];
tempForTimestamp[1] = waveData[289];
tempForTimestamp[2] = waveData[288];
tempForTimestamp[3] = waveData[287];
int number = BitConverter.ToInt32(tempForTimestamp, 0);
还有其他方法可以实现这种转换吗?
I am making application in C# which has a byte array containing hex values.
I am getting data as a big-endian but I want it as a little-endian and I am using Bitconverter.toInt32
method for converting that value to integer.
My problem is that before converting the value, I have to copy that 4 byte data into temporary array from source byte array and then reverse that temporary byte array.
I can't reverse source array because it also contains other data.
Because of that my application becomes slow.
In the code I have one source array of byte as waveData[]
which contains a lot of data.
byte[] tempForTimestamp=new byte[4];
tempForTimestamp[0] = waveData[290];
tempForTimestamp[1] = waveData[289];
tempForTimestamp[2] = waveData[288];
tempForTimestamp[3] = waveData[287];
int number = BitConverter.ToInt32(tempForTimestamp, 0);
Is there any other method for that conversion?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
添加对 System.Memory nuget 的引用并使用 BinaryPrimitives.ReverseEndianness()。
它支持有符号和无符号整数(字节/短/整数/长)。
Add a reference to System.Memory nuget and use BinaryPrimitives.ReverseEndianness().
It supports both signed and unsigned integers (byte/short/int/long).
如果您知道数据是大端字节序,也许只需手动执行即可:
这也可以在任何 CPU 上可靠地工作。注意
i
是当前缓冲区的偏移量。另一种方法是对数组进行洗牌:
我发现第一个方法的可读性非常高,并且没有分支/复杂的代码,因此它也应该工作得相当快。第二个也可能在某些平台上遇到问题(CPU 已经运行大端)。
If you know the data is big-endian, perhaps just do it manually:
this will work reliably on any CPU, too. Note
i
is your current offset into the buffer.Another approach would be to shuffle the array:
I find the first immensely more readable, and there are no branches / complex code, so it should work pretty fast too. The second could also run into problems on some platforms (where the CPU is already running big-endian).
在现代的 Linq 中,最简单、最容易理解的版本是:
你也可以...
:)
In modern-day Linq the one-liner and easiest to understand version would be:
You could also...
:)
最直接的方法是使用 .NET Standard 2.1 中引入的 BinaryPrimitives.ReadInt32BigEndian(ReadOnlySpan) 方法
The most straightforward way is to use the BinaryPrimitives.ReadInt32BigEndian(ReadOnlySpan) Method introduced in .NET Standard 2.1
干得好
Here you go
声明此类:
示例,创建一个带有按钮和多行文本框的表单:
Declare this class:
Example, create a form with a button and a multiline textbox:
我使用以下辅助函数
I use the following helper functions
如果您不再需要那个反向的临时数组,您可以在传递参数时创建它,而不是进行四次赋值。例如:
If you won't ever again need that reversed, temporary array, you could just create it as you pass the parameter, instead of making four assignments. For example:
您还可以使用 Jon Skeet“Misc Utils”库,位于 https://jonskeet.uk/csharp/miscutil /
他的库有很多实用函数。对于大/小尾数转换,您可以检查
MiscUtil/Conversion/EndianBitConverter.cs
文件。他的软件是 2009 年的,但我想它仍然有用。
You can also use Jon Skeet "Misc Utils" library, available at https://jonskeet.uk/csharp/miscutil/
His library has many utility functions. For Big/Little endian conversions you can check the
MiscUtil/Conversion/EndianBitConverter.cs
file.His software is from 2009 but I guess it's still relevant.
我不喜欢
BitConverter
,因为(正如 Marc Gravell 回答的那样)它被指定依赖于系统字节顺序,这意味着从技术上讲,您每次使用BitConverter
时都必须执行系统字节顺序检查确保您不必反转数组。通常,对于保存的文件,您通常知道您要读取的字节顺序,但这可能不一样。您可能也只是处理具有大端值的文件格式,例如 PNG 块。因此,我只是为此编写了自己的方法,该方法采用字节数组、读取偏移量和读取长度作为参数,以及用于指定字节序处理的布尔值,并使用位移来提高效率:
此代码可以处理 1 到 8 个字节之间的任何值,包括小端字节序和大端字节序。唯一的小用法特点是您需要给出要读取的字节数,并且需要将结果专门转换为您想要的类型。
一些代码的示例,我用它来读取某些专有图像类型的标头:
这将从数组中读取两个连续的 16 位整数,作为有符号的小端值。您当然可以为所有可能性创建一堆重载函数,如下所示:
但就我个人而言,我并没有为此烦恼。
并且,写入字节也是如此:
这里唯一的要求是,在将输入 arg 传递给函数时,必须将其转换为 64 位无符号整数。
I dislike
BitConverter
, because (as Marc Gravell answered) it is specced to rely on system endianness, meaning you technically have to do a system endianness check every time you useBitConverter
to ensure you don't have to reverse the array. And usually, with saved files, you generally know the endianness you're trying to read, and that might not be the same. You might just be handling file formats with big-endian values, too, like, for instance, PNG chunks.Because of that, I just wrote my own methods for this, which take a byte array, the read offset and read length as arguments, as well as a boolean to specify the endianness handling, and which uses bit shifting for efficiency:
This code can handle any value between 1 and 8 bytes, both little-endian and big-endian. The only small usage peculiarity is that you need to both give the amount of bytes to read, and need to specifically cast the result to the type you want.
Example from some code where I used it to read the header of some proprietary image type:
This will read two consecutive 16-bit integers off an array, as signed little-endian values. You can of course just make a bunch of overload functions for all possibilities, like this:
But personally I didn't bother with that.
And, here's the same for writing bytes:
The only requirement here is that you have to cast the input arg to 64-bit unsigned integer when passing it to the function.
与 @GeorgePolevoy 的回答类似,但应该使用
AsSpan(287)
来代替:根据我的测试,使用
AsSpan()
的速度比不使用的快约 2-2.5 倍。更多详细信息请参见此处,来自 Microsoft 文档。这是检查您的机器的计时测试:
Similar to what @GeorgePolevoy answered but
AsSpan(287)
should be used instead:Using
AsSpan()
is around 2-2.5x faster from my tests than the one without. More details here from Microsoft documentation.Here is a timing test to check on your machine:
如果允许不安全...基于 Marc Gravell 的帖子
If unsafe is allowed... Based on Marc Gravell's post
如果允许不安全代码,这将反转内联数据......
This will reverse the data inline if unsafe code is allowed...