Zlib для Mono / .Net без известной контрольной суммы - PullRequest
0 голосов
/ 07 мая 2009

Мне нужно реализовать специальную реализацию ZLib, которая должна работать под .Net и Mono. Сообщения данных / строк принимаются через сокет и, следовательно, контрольная сумма отсутствует. Это касается необработанных строковых данных, а не файлов.

    unsigned char zlib_header[]={
// custom additional Zlib Id
       'Z',    // Our own ID
// The normal GZIP header
       0x1f,
       0x8b,   // GZIP ID
       0x08,   // Deflated
       0x00,   // Flags
       0, 0, 0, 0, // Timestamp,
       0x00,   // Extra flags
       0x00,   // OS identifier
// afterwards compressed data without a checksum
};

Я пытался распаковать данные с помощью GZipStream и DeflateStream, но я думаю, что GZStream дает сбой из-за пропущенной контрольной суммы. Я также пробовал различные смещения, но не повезло. Контрольная сумма не используется, потому что данные все равно принимаются через сокет - таким образом, контрольная сумма ZLib будет дополнительными издержками. Я что-то пропустил или не могли бы вы мне объяснить, как добавить контрольную сумму и вызвать нужную библиотеку, или мне следует обратиться к сторонней библиотеке, которая поддерживает Mono и .Net? Изменить: производительность очень важна, так как это делается по крайней мере раз в секунду. Вы бы порекомендовали мне в конце использовать C-Lib через Interop? В настоящее время я всегда получаю исключение недействительных данных и предполагаю, что оно связано с неверной контрольной суммой. Это фактический код, который я пытался использовать без успеха:

const int HeaderSize = 1;
System.IO.MemoryStream ms = new System.IO.MemoryStream(compressedBuffer, HeaderSize, compressedBuffer.Length-HeaderSize);//remove the additional Z from the header
GZipStream zipStream = new GZipStream(ms, CompressionMode.Decompress,true);
byte[] deCompressedBytes = new byte[actualBufferLength* 10];
int resultSize=zipStream.Read(deCompressedBytes, 0, actualBufferLength);//get rid of the header      
UTF8Encoding enc = new UTF8Encoding();
string result = enc.GetString(deCompressedBytes, 0, resultSize);

Ответы [ 2 ]

2 голосов
/ 08 мая 2009

Вы уверены, что это связано с контрольной суммой?

32-битная контрольная сумма не является обязательной в формате GZIP. Я не понимаю, что вы подразумеваете под "данные получены через сокет, поэтому контрольная сумма отсутствует". Неважно, если вы получите данные через почтового голубя; если это действительный поток GZIP, он должен иметь 32-битный CRC. Кто или что предоставило исходные данные?

В спецификации GZIP есть дополнительная часть - 16-битная контрольная сумма. (его включение также не основано на том, как был создан поток GZIP.) Класс System.IO.GZipStream с радостью примет поток GZIP, в котором отсутствует этот CRC16, а также поток, который его включает.

У вас есть другие проблемы в коде. Фактическая BufferLength в вашем коде - что это? Это, конечно, не длина буфера для хранения распакованных данных. Это в 10 раз. Но 10х кажется довольно произвольным. Для очень сжимаемых данных вы можете превысить 10x. Я предлагаю вам использовать потоковый подход в декомпрессии.

Что касается того, сможете ли вы обрабатывать распаковку со скоростью 1 в секунду, да, System.IO.GZipStream будет достаточно быстрым для достаточно маленьких кусков данных. Скорее всего, нет нужды обращаться к собственной библиотеке C / C ++.

ps: библиотека DotNetZip включает GZipStream с открытым исходным кодом; Вы можете использовать его из коробки или, если хотите, можете просто взять GZip, если это все, что вам нужно.

1 голос
/ 08 мая 2009

Просто используйте DeflateStream вместо GZipStream.

...