如何将数字转换为字节数组(按位端顺序)

How to convert a number to a bytearray in bit endian order

本文关键字:顺序 数组 字节数 数字 转换 字节      更新时间:2023-10-16

我正在尝试使用zlib API解压缩在VB6中创建的一些数据。

我已经阅读了qUncompress函数:http://doc.trolltech.com/4.4/qbytearray.html#qUncompress

我已经通过readRawBytes将QDataStream中的数据读取为一个字符数组,然后我将其转换为QByteArray进行解压缩。我有压缩的长度和预期的解压缩长度,但我没有得到从qUncompress返回的任何内容。

然而,我需要以big-endian格式预先准备预期的解压缩长度。有人做过这件事并有一个例子吗?

我在时代中没有使用过VB6,所以我希望这是大致正确的。我认为vb6将()用于数组索引。如果我做错了什么,请告诉我。

查看qUncompress文档,您应该将数据放在QByteArray中,从字节5开始(在本例中,我假设您将数组索引基数设置为1)。

假设数组名为qArr,预期的未压缩大小为size。在"big-endian"表示中,第一个字节位于第一个地址。

qArr(1) = int(Size/(256*256*256))
qArr(2) = 255 And int(Size/256*256)
qArr(3) = 255 And int(Size/256)
qArr(4) = 255 And int(Size)

这有道理吗?

如果您需要little-endian,您可以颠倒索引的顺序(qArr(4)-qArr(1)),并保持计算不变。

这就是我如何将任意数据从一种格式转换为另一种格式。

Private Type LongByte
    H1 As Byte
    H2 As Byte
    L1 As Byte
    L2 As Byte
End Type
Private Type LongType
    L As Long
End Type
Function SwapEndian(ByVal LongData as Long) as Long
  Dim TempL As LongType
  Dim TempLB As LongByte
  Dim TempVar As Long
  TempL.L = LongData
  LSet TempLB = TempL
'Swap is a subroutine I wrote to swap two variables
  Swap TempLB.H1, TempLB.L2
  Swap TempLB.H2, TempLB.L1
  LSet TempL = TempLB
  TempVar = TempL.L
  SwapEndian = TempVar
End Function

如果您正在处理FileIO,那么您可以使用TempLB 的Byte字段

诀窍是使用LSET VB6 的一个模糊命令

如果您正在使用。NET,那么做这个过程就容易多了。这里的技巧是使用MemoryStream来检索和设置单个字节。现在你可以计算int16/int32/int64。但是,如果您正在处理浮点数据,那么使用LSET或MemoryStream会更清晰、更容易调试。

如果您使用的是Framework 1.1或更高版本,那么您拥有使用字节数组的BitConvertor类。

Private Structure Int32Byte
    Public H1 As Byte
    Public H2 As Byte
    Public L1 As Byte
    Public L2 As Byte
    Public Function Convert() As Integer
        Dim M As New MemoryStream()
        Dim bR As IO.BinaryReader
        Dim bW As New IO.BinaryWriter(M)
        Swap(H1, L2)
        Swap(H2, L1)
        bW.Write(H1)
        bW.Write(H2)
        bW.Write(L1)
        bW.Write(L2)
        M.Seek(0, SeekOrigin.Begin)
        bR = New IO.BinaryReader(M)
        Convert = bR.ReadInt32()
    End Function
End Structure

看起来您想要一个C代码块来解压缩一些zlib压缩数据。在这种情况下,您是否可以实际使用zlib并将zlib数据提供给它。zlib主页:http://www.zlib.net/.

如果我弄错了,你能具体说明应该使用什么语言来解压缩数据吗?为什么zlib不是一个选择?

//int length;
byte[] bigEndianBytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(length))

相反:

//byte[] bigEndianBytes;
int length = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(bigEndianBytes))

从您的问题中,我不清楚您是想在VB中预先设置长度,使其适合qUncompress直接使用,还是想像现在这样使用VB生成的数据,并在调用qUncompression之前在C++中预先设置长度。

Mike G发布了一个VB解决方案。如果你想在C++中完成,那么你有两个选择,要么在QByteArray的开头添加长度,要么直接调用zlib的uncompress。在这两种情况下,qCompress和qUncompress的Qt源代码(corelib/tools/qbyterarray.cpp)都是一个很好的参考。

这就是qCompress如何将长度(nbytes)添加到bazip,即压缩数据:

bazip[0] = (nbytes & 0xff000000) >> 24;
bazip[1] = (nbytes & 0x00ff0000) >> 16;
bazip[2] = (nbytes & 0x0000ff00) >> 8;
bazip[3] = (nbytes & 0x000000ff);

其中bazip是QByteArray 的结果

或者,如果你想直接调用uncompress,而不是使用qUncompress包装器,它使用的调用是

baunzip.resize(len);
res = ::uncompress((uchar*)baunzip.data(), &len,
                        (uchar*)data+4, nbytes-4);

其中baunzip是QByteArray。在您的情况下,您将删除+4和-4,因为您的数据没有预先准备好长度。

感谢您的帮助,非常有用。

我得到了可以使用的代码:

        char slideStr[currentCompressedLen];
        int slideByteRead = in.readRawData(slideStr, currentCompressedLen);
        QByteArray aInCompBytes = QByteArray(slideStr, slideByteRead);
        aInCompBytesPlusLen = aInCompBytes;
        aInCompBytesPlusLen.prepend(QByteArray::number(currentUnCompressedLen));
        aInUnCompBytes.resize(currentUnCompressedLen);
        aInUnCompBytes = qUncompress(aInCompBytesPlusLen);