[英]Converting Byte Array To Int24
I am reading a file with BinaryReader. 我正在使用BinaryReader读取文件。
There are data I want to pull at the address 0x37E but it is int24. 我想在地址0x37E处提取数据,但它是int24。 So even I read 3 bytes, I can't convert it to int24.
因此,即使我读取了3个字节,也无法将其转换为int24。
Do you have any suggestion? 你有什么建议吗?
I'm using C# and am working on STFS package stuff. 我正在使用C#,并且正在处理STFS软件包中的东西。
In order to transform a byte array to an int24, you need to know the endianness of the data. 为了将字节数组转换为int24,您需要了解数据的字节序。 This means: the information if
11 22 33
is supposed to mean 0x112233
or 0x332211
. 这意味着:
11 22 33
应该表示0x112233
还是0x332211
。
Depending on this endianness, you can convert the data such as 根据这种字节顺序,您可以转换数据,例如
int24 result_bigendian = array[0] * 65536 + array[1] * 256 + array[2] // (1)
or 要么
int24 result_littleendian = array[2] * 65536 + array[1] * 256 + array[0] // (2)
(resp. (分别
int24 result_littleendian = array[0] + array[1] * 256 + array[2] * 65536 // (3)
if you prefer that; 如果您愿意的话; note the difference to (1))
注意与(1)的区别)
I don't know about C#; 我不了解C#; there may be an easier way to reach the goal.
可能有更简单的方法可以达到目标。
For signed int24, little endian use: 对于带符号的int24,使用小尾数法 :
int num = array[0] | array[1] << 8 | (sbyte)array[2] << 16;
For signed int24, big endian use: 对于带符号的int24,大端使用:
int num = (sbyte)array[0] << 16 | array[1] << 8 | array[2];
For unsigned int24, little endian use: 对于unsigned int24,使用小尾数法 :
int num = array[0] | array[1] << 8 | array[2] << 16;
For unsigned int24, big endian use: 对于unsigned int24,big endian使用:
int num = array[0] << 16 | array[1] << 8 | array[2];
Note that for any signed int, little endian of n bytes, just list all the bytes, connect them using a '|', shift them one by one, and add (sbyte) to the last byte to make it signed: 请注意,对于任何带符号的int, n个字节的小尾数 ,只需列出所有字节,使用'|' 连接它们, 将它们一一移位 ,然后将(sbyte)加到最后一个字节以使其成为符号:
var num = array[0] | array[1] << 8 | array[2] << 16 | ... | (sbyte)array[n] << 8*n;
For big endian , just reverse the shift order: 对于大端 ,只需反转移位顺序即可:
var num = array[n] | array[n-1] << 8 | array[n-2] << 16 | ... | (sbyte)array[0] << 8*n;
Or, of course, alternatively: 或者,当然也可以:
var num = (sbyte)array[0] << 8*n | array[1] << 8*(n-1) | ... | array[0];
You have to make sure that the (sbyte) is with the highest order byte (the last byte if little endian, the first byte if big endian) to get C# create the sign for the int. 您必须确保(sbyte)具有最高顺序字节 (如果是小端则为最后一个字节,如果是大端则为第一个字节)以获取C#创建int的符号。
Of course, for unsigned int , just remove the (sbyte) . 当然,对于unsigned int ,只需删除(sbyte)即可 。
Last thing.. the array can be byte[] or int[] . 最后一件事.. 数组可以是byte []或int [] 。 So you can do this:
因此,您可以执行以下操作:
var num = stream.ReadByte() | stream.ReadByte() << 8 | (sbyte)stream.ReadByte() << 16;
Where stream is a System.IO.Stream . 其中stream是System.IO.Stream 。
I have written an extension method for this problem some time ago. 我前一段时间已经为这个问题写了一个扩展方法。
public enum Endian : int {
Little,
Big
}
public static int ToInt32(this byte[] buffer, Endian endian = Endian.Little) {
if (buffer.Length < 1 || buffer.Length > 4)
throw new ArgumentException(" ... ");
if (endian == Endian.Big)
buffer.Reverse();
int sum = 0;
for (int i = buffer.Length - 1; i > -1; --i)
sum += (buffer[i] << (i << 3));
if ((buffer[buffer.Length - 1] & 0x80) == 0x80)
sum |= (0xFFFFFF << (buffer.Length << 3));
return sum;
}
public static unsafe void Reverse(this byte[] buffer) {
fixed (byte* b = buffer) {
byte* s, e;
s = b;
e = b + buffer.Length - 1;
byte t;
while (s < e) {
t = *s;
*s = *e;
*e = t;
++s;
--e;
}
}
}
The Endian enum and the Reverse method are used by the ToInt32 method for Endian purposes. ToInt32方法将Endian枚举和Reverse方法用于Endian。
The ToInt32 method has some nice benefits: ToInt32方法有一些不错的好处:
1. It's an extension method so you can call it with your byte[] object. 1.这是一个扩展方法,因此您可以使用byte []对象来调用它。
byte[] x = { 0xFF, 0xFF, 0x7F };
int value = x.ToInt32();
2. It's able to convert the byte array to both byte orders. 2.能够将字节数组转换为两个字节顺序。
byte[] x = { 0x12, 0x34, 0x56 };
int valueLittle = x.ToInt32(Endian.Little); // Return 5,649,426
int valueBig = x.ToInt32(Endian.Big); // Return 1,193,046
3. It takes care of the sign bit. 3.它负责符号位。
byte[] x = { 0x00, 0x00, 0x80 };
x.ToInt32(); // Return -8,388,608
x.ToInt32(Endian.Big); // Return 128
I've tried to make the methods so fast as I can. 我试图使这些方法尽可能快。 Did some benchmarks and speed was good for me.
进行一些基准测试和速度测试是否对我有利。
Hope this solution helps and makes the life easier. 希望此解决方案能够帮助您,使生活更轻松。 ;)
;)
Just to complement @glglgl answer, in C# you can try the following: 只是为了补充@glglgl答案,在C#中,您可以尝试以下操作:
public int ReadInt24(byte[] array, int pos)
{
if(array == null || array.Length < 3)
return -1; //some invalid value
if (BitConverter.IsLittleEndian)
return ((array[2]) + (array[1] * 256) + (array[0] * 65536));
else
return ((array[0]) + (array[1] * 256) + (array[2] * 65536));
}
The property BitConverter.IsLittleEndian will tell about the current Endianness 属性BitConverter.IsLittleEndian将说明当前的字节序
Indicates the byte order ("endianness") in which data is stored in this computer architecture.
指示在此计算机体系结构中存储数据的字节顺序(“字节序”)。
对于带符号的int24使用:
int num = array[0] | array[1] << 8 | (sbyte)array[2] << 16;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.