Как преобразовать число в байтовый массив в порядке байтов - PullRequest
4 голосов
/ 07 октября 2008

Я пытаюсь распаковать некоторые данные, созданные в VB6 с помощью API zlib.

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

Я прочитал данные из QDataStream через readRawBytes в символ массив, который я затем преобразовал в QByteArray для распаковки. я имеют сжатую длину и ожидаемую распакованную длину, но я не получаю что-нибудь от qUncompress.

Однако мне нужно добавить ожидаемую распакованную длину в формате с прямым порядком байтов. Кто-нибудь сделал это и есть пример?

Ответы [ 6 ]

2 голосов
/ 07 октября 2008

Я не использовал VB6 в возрасте , поэтому я надеюсь, что это примерно правильно. Я думаю , что vb6 использовал () для индексации массива. Если я ошибаюсь, пожалуйста, дайте мне знать.

Глядя на документы qUncompress, вы должны были поместить свои данные в свой QByteArray, начиная с байта 5 (я собираюсь предположить, что вы оставили для базы индекса индекса значение 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)) и оставить вычисления одинаковыми.

1 голос
/ 07 октября 2008

Так я могу конвертировать произвольные данные из одного формата в другой.

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, вы можете использовать поля Byte в 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
0 голосов
/ 07 октября 2008

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

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

        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);
0 голосов
/ 07 октября 2008

Из вашего вопроса мне было непонятно, хотите ли вы предварительно добавить длину в VB, чтобы она подходила для непосредственного использования qUncompress, или вы хотели использовать данные, полученные в VB, как есть сейчас, и добавить длину в C ++ перед вызовом qUncompress.

Майк G опубликовал 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, так как к вашим данным не добавлена ​​длина.

0 голосов
/ 07 октября 2008
//int length;
byte[] bigEndianBytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(length))

И наоборот:

//byte[] bigEndianBytes;
int length = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(bigEndianBytes))
0 голосов
/ 07 октября 2008

Похоже, вы хотите кусок кода C, который распаковывает некоторые сжатые zlib данные. В этом случае возможно ли вам использовать zlib и просто передавать ему данные zlib. Домашняя страница zlib: http://www.zlib.net/.

Если я ошибся, не могли бы вы уточнить, какой язык следует использовать для распаковки данных и почему zlib не будет выбором?

...