Различия в сжатии Zlib между реализацией zlib.c Adler и Deflate, Ionic Deflate - PullRequest
3 голосов
/ 08 марта 2019

У меня возникли проблемы с несовместимостью между разностными реализациями сжатия zlib.

В качестве тестового примера я подумал создать тестовые данные с 10000 double с в диапазоне от 0 до 10000.

Я создал некоторый тестовый код для сжатия и распаковки этих данных, который использует сжатие и распаковку в zlib.c

unsigned int Test(char* comparisonFile)
{
    unsigned long partsSize = 0x80000;
    const int arraySize = 10000;
    Bytef doubleArray[sizeof(double) * arraySize];
    Bytef outBuffer[sizeof(double) * arraySize];

    for (int i = 0; i < arraySize; i++)
    {
        Bytef doubleBytes[sizeof(double)];
        *(double*)(doubleBytes) = (double)i;
        for (int x = 0; x < 8; x++)
            doubleArray[(8 * i) + x] = doubleBytes[x];
    }
    compress(outBuffer, &partsSize, doubleArray, sizeof(double) * arraySize);

    //create file of compressed data
    char * filename = "zlibCompressed";
    FILE * file = fopen(filename, "w+b");
    int compressResult = et_int64(fwrite((char *)outBuffer, 1, size_t(partsSize), file));
    fclose(file);

    //load  file of compressed data either from zlib or other
    if (comparisonFile != NULL)
        filename = comparisonFile;
    FILE * compressedFile = fopen(filename, "r+b");
    if (compressedFile == NULL)
        return -1;

    unsigned long outBufferSize = sizeof(double) * arraySize;
    fseek(compressedFile, 0, SEEK_END);
    long fsize = ftell(compressedFile);
    fseek(compressedFile, 0, SEEK_SET);  /* same as rewind(f); */
    partsSize = int(fsize);

    double * doubleResult = new double [arraySize];
    Bytef* inBuffer = (Bytef*)malloc(sizeof(Bytef)*partsSize);
    int readresult = et_int64(fread((char *)inBuffer, 1, partsSize , compressedFile));

    if (readresult != partsSize)
        return -1;

    Bytef *  uncompressedOutBuffer = static_cast<Bytef*>((void *)doubleResult);
    int result = uncompress(uncompressedOutBuffer, &outBufferSize, inBuffer, partsSize);

    for (int i = 0; i < arraySize; i++)
    {
        // uncompressed data does not match expectation
        if ((int)doubleResult[i] != i)
            return -2;
    }
    fclose(compressedFile);
    return 0;

}

Это позволяет мне проверять внутреннее сжатие, а также подставлятьрезультаты сжатия от C#.

Однако, когда я использую ионный или стандартный дефлят следующим образом, я могу получить только 8150 ожидаемого 10000 .

Распаковка возвращает:

Z_DATA_ERROR

Учитывая, что в теории они кажутся совместимыми, я не уверен, почему C# результаты сжатия могуттолько частично распаковать с адлерским zlib?Любая помощь там?

public void ZlibTest()
        {
            byte[] buffer;
            using (var ms = new MemoryStream())
            {
                for (int i = 0; i < 10000; i++)
                    ms.Write(BitConverter.GetBytes((double) i), 0, sizeof(double));
                buffer = ms.ToArray();
            }

            var file = "dummy1";

            if (File.Exists(file))
                File.Delete(file);


            using (Stream fs = new FileStream(file, FileMode.OpenOrCreate, FileAccess.ReadWrite))
            {
                using (var resultStream = new MemoryStream())
                {
                    using (var compressionStream2 = new Ionic.Zlib.ZlibStream(resultStream, Ionic.Zlib.CompressionMode.Compress, CompressionLevel.Default))
                    {
                        compressionStream2.Write(buffer, 0, buffer.Length);
                        var packetLength = (int)resultStream.Length;
                        fs.Write(resultStream.ToArray(), 0, packetLength);
                    }
                }
            }

            file = "dummy2";
            using (Stream fs = new FileStream(file, FileMode.OpenOrCreate, FileAccess.ReadWrite))
            {
                using (var resultStream = new MemoryStream())
                {
                    using (var compressionStream2 = new System.IO.Compression.DeflateStream(resultStream, System.IO.Compression.CompressionMode.Compress))
                    {
                        compressionStream2.Write(buffer, 0, buffer.Length);
                        var packetLength = (int)resultStream.Length;
                        fs.Write(BitConverter.GetBytes((ushort)40056), 0, sizeof(ushort));
                        fs.Write(resultStream.ToArray(), 0, packetLength);
                    }
                }
            }
        }

1 Ответ

0 голосов
/ 09 марта 2019

Они оба используют один и тот же zlib.В вашем коде C # должна быть ошибка.Возможно, вы не читаете файл в двоичном режиме в C #, что может привести к случайному повреждению.

...