5

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

我已经阅读了 qUncompress 函数可以做到这一点:http: //doc.trolltech.com/4.4/qbytearray.html#qUncompress

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

但是,我需要以大端格式添加预期的解压缩长度。有没有人这样做并有一个例子?

4

6 回答 6

2

我已经很久没有使用过 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)) 并保持计算不变。

于 2008-10-07T09:48:37.700 回答
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 的字节字段

诀窍是使用 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
于 2008-10-07T12:52:54.850 回答
0

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

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

于 2008-10-07T10:04:21.727 回答
0
//int length;
byte[] bigEndianBytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(length))

反过来:

//byte[] bigEndianBytes;
int length = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(bigEndianBytes))
于 2008-10-07T10:27:35.843 回答
0

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

Mike G发布了一个 VB 解决方案。如果你想用 C++ 来做,那么你有两个选择,要么在 QByteArray 的开头添加长度,要么直接调用 zlib 的 uncompress。在这两种情况下,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,因为您的数据没有附加长度。

于 2008-10-07T13:00:55.300 回答
0

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

我得到了使用的代码:

        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);
于 2008-10-07T15:20:57.047 回答