Как преобразовать число в bytearray в порядке окончания бита

StackOverflow https://stackoverflow.com/questions/177677

Вопрос

Я пытаюсь распаковать некоторые данные, созданные в VB6, используя zlib API.

Я читал, что это возможно с помощью функции qUncompress:http://doc.trolltech.com/4.4/qbytearray.html#qUncompress

Я прочитал данные из QDataStream через readRawBytes в массив char , который затем преобразовал в 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)

Это имеет смысл?

Если вам нужен порядок байтов с прямым порядком байтов, вы можете просто изменить порядок индексов (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

Хитрость заключается в использовании 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, как сейчас, и добавить длину в C ++ перед вызовом qUncompress.

У Майка Джи есть размещенный решение на языке VB.Если вы хотите сделать это на C ++, то у вас есть два варианта: либо добавить длину в начале QByteArray, либо напрямую вызвать распаковку zlib.В обоих случаях хорошим справочником являются исходные тексты Qt для qCompress и qUncompress (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, поскольку к вашим данным не добавляется длина.

Спасибо за вашу помощь, это было полезно.

Я получил код, работающий с:

        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