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

发布于 2024-07-06 02:25:13 字数 422 浏览 10 评论 0原文

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

我读过 qUncompress 函数可以实现这一点: http://doc.trolltech.com/4.4/qbytearray.html#qUncompress

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

但是,我需要以大端格式预先考虑预期的解压缩长度。 有人做过这个并有例子吗?

I am trying to uncompress some data created in VB6 using the zlib API.

I have read this is possible with the qUncompress function:
http://doc.trolltech.com/4.4/qbytearray.html#qUncompress

I have read the data in from QDataStream via readRawBytes into a char
array, which I then converted to a QByteArray for decompression. I
have the compressed length and the expected decompressed length but am not getting
anything back from qUncompress.

However I need to prepend the expected decompressed length in big endian format. Has anybody done this and have an example?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

新人笑 2024-07-13 02:25:14

感谢您的所有帮助,这很有用。

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

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

Thank you for all your help, it was useful.

The I got the code working with:

        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);
↙温凉少女 2024-07-13 02:25:14
//int length;
byte[] bigEndianBytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(length))

反过来:

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

Conversely:

//byte[] bigEndianBytes;
int length = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(bigEndianBytes))
寂寞清仓 2024-07-13 02:25:14

从你的问题中我不清楚你是否想要在 VB 中添加长度以便它适合 qUncompress 直接使用,或者你是否想像现在一样使用 VB 生成的数据并在之前在 C++ 中添加长度调用 qUncompress。

Mike G 已发布了 VB 解决方案。 如果您想在 C++ 中执行此操作,那么您有两种选择,要么在 QByteArray 的开头添加长度,要么直接调用 zlib 的解压缩。 在这两种情况下,qCompress 和 qUncompress 的 Qt 源代码 (corelib/tools/qbytearray.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,因为您的数据没有预先添加长度。

It wasn't clear to me from your question whether you want to prepend the length in VB so that it is suitable for direct use by qUncompress or whether you wanted to use the VB produced data as it is now and prepend the length in C++ before calling qUncompress.

Mike G has posted a VB solution. If you want to do it in C++ then you have two choices, either add the length at the start of the QByteArray or call zlib's uncompress directly. In both cases the Qt source for qCompress and qUncompress (corelib/tools/qbytearray.cpp) are a good reference.

This is how qCompress adds the length (nbytes) to bazip, the compressed data:

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

where bazip is the result QByteArray

Alternatively if you want to call uncompress directly, instead of using the qUncompress wrapper the call it uses is

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

where baunzip is a QByteArray. In your case you would drop the +4 and -4 since your data does not have the length prepended to it.

我为君王 2024-07-13 02:25:13

我已经多年没有使用过VB6了,所以我希望这大致是正确的。 我认为 vb6 使用 () 进行数组索引。 如果我有任何问题,请告诉我。

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

假设该数组名为 qArr,预期的未压缩大小为 Size。
在“大端”表示中,第一个字节位于第一个地址。

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)

那有意义吗?

如果您需要小尾数,您可以反转索引的顺序 (qArr(4) - qArr(1)) 并保持计算不变。

I haven't used VB6 in ages, so I hope this is approximately correct. I think that vb6 used () for array indexing. If I got anything wrong, please let me know.

Looking at the qUncompress docs, you should have put your data in your QByteArray starting at byte 5 (I'm going to assume that you left the array index base set to 1 for this example).

Let's say the array is named qArr, and the expected uncompressed size is Size.
In a "big-endian" representation, the first byte is at the first address.

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)

Does that make sense?

If you needed little endian, you could just reverse the order of the indexes (qArr(4) - qArr(1)) and leave the calculations the same.

菩提树下叶撕阳。 2024-07-13 02:25:13

这就是我将任意数据从一种格式转换为另一种格式的方法。

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 的字节字段。

技巧是使用 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

This is how I can convert arbitary data from one format to another.

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

If you are dealing with FileIO then you can use the Byte fields of TempLB

The trick is using LSET an obscure command of VB6

If you are using .NET then doing the process is much easier. Here the trick is using a MemoryStream to retrieve and set the individual bytes. Now you could do math for int16/int32/int64. But if you are dealing with with floating point data, using LSET or the MemoryStream is much clearer and easier to debug.

If you are using Framework version 1.1 or beyond then you have the BitConvertor Class which uses arrays of bytes.

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
红ご颜醉 2024-07-13 02:25:13

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

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

It looks like you want a C chunk of code that uncompresses some zlib compressed data.
In that case is it possible for you to actually use zlib and just feed the zlib data to it. The zlib homepage: http://www.zlib.net/.

If I got it wrong, could you be specific what is the language that should be used for uncompressing the data and why zlib would not be a choice?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文