Как преобразовать число в bytearray в порядке окончания бита
-
05-07-2019 - |
Вопрос
Я пытаюсь распаковать некоторые данные, созданные в 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);