質問

zlib APIを使用してVB6で作成されたデータを解凍しようとしています。

これは、qUncompress関数で可能です。 http://doc.trolltech.com/4.4/qbytearray.html#qUncompress

QRStreamからreadRawBytesを介してcharにデータを読み込みました 配列。これを解凍のためにQByteArrayに変換しました。私 圧縮された長さと予想される解凍された長さを持っているが、取得していない qUncompressから返されたもの。

ただし、予想される解凍後の長さをビッグエンディアン形式で追加する必要があります。誰かがこれを行って、例を持っていますか?

役に立ちましたか?

解決

年齢で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))、計算を同じままにすることができます。

他のヒント

これにより、任意のデータをある形式から別の形式に変換できます。

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

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

.NETを使用している場合、プロセスを実行する方がはるかに簡単です。ここでの秘theは、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

一部のzlib圧縮データを圧縮解除するCのチャンクが必要なようです。 その場合、実際に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で生成されたデータをそのまま使用して長さを先頭に追加するのかは、質問からわかりませんでしたqUncompressを呼び出す前にC ++で。

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

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

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);
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top