将字节数组转换为Int24

我正在使用BinaryReader读取文件。

我想要在地址0x37E处提取数据,但它是int24。 所以即使我读了3个字节,我也无法将其转换为int24。

你有什么建议吗?

我正在使用C#并正在研究STFS包的东西。

为了将字节数组转换为int24,您需要知道数据的字节顺序。 这意味着:如果11 22 33应该表示0x1122330x332211

根据此字节顺序,您可以转换数据,如

 int24 result_bigendian = array[0] * 65536 + array[1] * 256 + array[2] // (1) 

要么

 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) 

如果你喜欢那个; 注意与(1)的区别

我不知道C#; 可能有更简单的方法来达到目标​​。

对于signed int24,小端使用:

 int num = array[0] | array[1] << 8 | (sbyte)array[2] << 16; 

对于signed int24,big endian使用:

 int num = (sbyte)array[0] << 16 | array[1] << 8 | array[2]; 

对于unsigned int24,小端使用:

 int num = array[0] | array[1] << 8 | array[2] << 16; 

对于unsigned int24,big endian使用:

 int num = array[0] << 16 | array[1] << 8 | array[2]; 

请注意,对于任何带符号的int, n个字节的小端 ,只列出所有字节,使用“|” 连接它们,逐个移位它们, 并将(sbyte)添加到最后一个字节以使其签名:

 var num = array[0] | array[1] << 8 | array[2] << 16 | ... | (sbyte)array[n] << 8*n; 

对于大端 ,只需反转class次顺序:

 var num = array[n] | array[n-1] << 8 | array[n-2] << 16 | ... | (sbyte)array[0] << 8*n; 

或者,当然,或者:

 var num = (sbyte)array[0] << 8*n | array[1] << 8*(n-1) | ... | array[0]; 

你必须确保(sbyte)具有最高阶字节 (最后一个字节,如果是小端,第一个字节,如果是大端),以获得C#创建int的符号。

当然,对于unsigned int ,只需删除(sbyte)


最后一件事...... 数组可以是byte []int [] 。 所以你可以这样做:

 var num = stream.ReadByte() | stream.ReadByte() << 8 | (sbyte)stream.ReadByte() << 16; 

其中streamSystem.IO.Stream

我前段时间已经为这个问题写了一个扩展方法。

 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; } } } 

Endian枚举Reverse方法由ToInt32方法用于Endian目的。

ToInt32方法有一些很好的好处:

1.这是一种扩展方法,因此您可以使用byte []对象调用它。

 byte[] x = { 0xFF, 0xFF, 0x7F }; int value = x.ToInt32(); 

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 

它照顾了标志位。

 byte[] x = { 0x00, 0x00, 0x80 }; x.ToInt32(); // Return -8,388,608 x.ToInt32(Endian.Big); // Return 128 

我试图尽可能快地制作这些方法。 一些基准和速度对我有好处。
希望这个解决方案有助于让生活更轻松。 ;)

只是为了补充@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)); } 

BitConverter.IsLittleEndian属性将告诉当前的Endianness

指示数据存储在此计算机体系结构中的字节顺序(“endianness”)。

对于signed int24使用:

 int num = array[0] | array[1] << 8 | (sbyte)array[2] << 16;