Zlib для Mono/.Net без известной контрольной суммы

Мне нужно реализовать специальную реализацию 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? Я всегда получаю Invalid Data Exception в данный момент, и я предполагаю, что это связано с неправильной контрольной суммой. Это фактический код, который я безуспешно пытался использовать:

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);

person weismat    schedule 07.05.2009    source источник


Ответы (2)


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

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

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

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

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

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

person Cheeso    schedule 08.05.2009
comment
Я интегрируюсь с третьей стороной из удаленного места, и у них, очевидно, есть ошибка в их программном обеспечении — они неправильно очищают сетевой поток. Спасибо за вашу помощь в любом случае. - person weismat; 10.05.2009

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

person lupus    schedule 08.05.2009