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 の Byte フィールドを使用できます。

トリックは、VB6のあいまいなコマンドであるLSETを使用することです

.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

qUncompressで直接使用できるように、VBで長さを追加するのか、それともVBで生成されたデータをそのまま使用して、以前のC++で長さを追加するのかはわかりませんでした。 qUncompressを呼び出します。

MikeGがVBソリューションを投稿しました。C ++で実行する場合は、QByteArrayの先頭に長さを追加するか、zlibのuncompressを直接呼び出すかの2つの選択肢があります。どちらの場合も、qCompressとqUncompressのQtソース(corelib / tools / qbytearray.cpp)が適切なリファレンスです。

これは、qCompressが圧縮データであるbazipに長さ(nbytes)を追加する方法です。

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

ここで、bazipは結果のQByteArrayです。

または、qUncompressラッパーを使用する代わりに、uncompressを直接呼び出す場合は、次のように呼び出します。

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 に答える
0

一部の zlib 圧縮データを解凍する C チャンクのコードが必要なようです。その場合、実際に 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 に答える