С# декодировать (распаковывать) Deflate данные файла PDF

Я хотел бы распаковать в С# некоторые данные DeflateCoded (извлеченный PDF). К сожалению, я каждый раз получал исключение «Обнаружены недопустимые данные при декодировании». Но данные верные.

private void Decompress()
{
    FileStream fs = new FileStream(@"S:\Temp\myFile.bin", FileMode.Open);

    //First two bytes are irrelevant
    fs.ReadByte();
    fs.ReadByte();

    DeflateStream d_Stream = new DeflateStream(fs, CompressionMode.Decompress);

    StreamToFile(d_Stream, @"S:\Temp\myFile1.txt", FileMode.OpenOrCreate);

    d_Stream.Close();
    fs.Close();
}

private static void StreamToFile(Stream inputStream, string outputFile, FileMode fileMode)
{
    if (inputStream == null)
        throw new ArgumentNullException("inputStream");

    if (String.IsNullOrEmpty(outputFile))
        throw new ArgumentException("Argument null or empty.", "outputFile");

    using (FileStream outputStream = new FileStream(outputFile, fileMode, FileAccess.Write))
    {
        int cnt = 0;
        const int LEN = 4096;
        byte[] buffer = new byte[LEN];

        while ((cnt = inputStream.Read(buffer, 0, LEN)) != 0)
            outputStream.Write(buffer, 0, cnt);
    }
}

У кого-нибудь есть идеи? Спасибо.


person user1011394    schedule 08.02.2012    source источник
comment
Почему первые два байта не имеют значения?   -  person    schedule 08.02.2012
comment
Декодер потока использует RFC1951. В сочетании с DeflateStreams первые два байта не имеют значения. Если потоковый декодер использует RC1950, то я также должен использовать первые байты.   -  person user1011394    schedule 08.02.2012
comment
Что вы сделали, чтобы доказать, что ошибка неверна и что данные действительно верны.   -  person Ben Robinson    schedule 08.02.2012


Ответы (4)


Я добавил это для тестовых данных: -

private static void Compress()
{
  FileStream fs = new FileStream(@"C:\Temp\myFile.bin", FileMode.Create);

  DeflateStream d_Stream = new DeflateStream(fs, CompressionMode.Compress);
  for (byte n = 0; n < 255; n++)
    d_Stream.WriteByte(n);
  d_Stream.Close();
  fs.Close();
}

Измененный декомпресс, как это: -

private static void Decompress()
{
  FileStream fs = new FileStream(@"C:\Temp\myFile.bin", FileMode.Open);

  //First two bytes are irrelevant
  //      fs.ReadByte();
  //      fs.ReadByte();

  DeflateStream d_Stream = new DeflateStream(fs, CompressionMode.Decompress);

  StreamToFile(d_Stream, @"C:\Temp\myFile1.txt", FileMode.OpenOrCreate);

  d_Stream.Close();
  fs.Close();
}

Запустил это так: -

static void Main(string[] args)
{
  Compress();
  Decompress();
}

И ошибок не было.

Я делаю вывод, что либо первые два байта имеют значение (очевидно, они относятся к моим конкретным тестовым данным), либо что у ваших данных есть проблема.

Можем ли мы получить некоторые из ваших тестовых данных для игры?

(Очевидно, нет, если это чувствительно)

person Community    schedule 09.02.2012

private static string decompress(byte[] input)
{
    byte[] cutinput = new byte[input.Length - 2];
    Array.Copy(input, 2, cutinput, 0, cutinput.Length);

    var stream = new MemoryStream();

    using (var compressStream = new MemoryStream(cutinput))
    using (var decompressor = new DeflateStream(compressStream, CompressionMode.Decompress))
        decompressor.CopyTo(stream);

    return Encoding.Default.GetString(stream.ToArray());
}

Спасибо, user159335 и user1011394, за то, что направили меня на правильный путь! Просто передайте все байты потока на вход вышеуказанной функции. Убедитесь, что количество байтов совпадает с указанной длиной.

person Pete    schedule 29.03.2018

Все, что вам нужно сделать, это использовать GZip вместо Deflate. Ниже приведен код, который я использую для содержимого раздела stream… endstream в документе PDF:

        using System.IO.Compression;

        public void DecompressStreamData(byte[] data)
        {

            int start = 0;
            while ((this.data[start] == 0x0a) | (this.data[start] == 0x0d)) start++; // skip trailling cr, lf

            byte[] tempdata = new byte[this.data.Length - start];
            Array.Copy(data, start, tempdata, 0, data.Length - start);

            MemoryStream msInput = new MemoryStream(tempdata);
            MemoryStream msOutput = new MemoryStream();
            try
            {
                GZipStream decomp = new GZipStream(msInput, CompressionMode.Decompress);
                decomp.CopyTo(msOutput);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }

        }
person Miroslav Sedivy    schedule 21.12.2019

Ни одно из решений не помогло мне с вложениями Deflate в документе PDF/A-3. Некоторые исследования показали, что .NET DeflateStream не поддерживает сжатые потоки с заголовком и трейлером в соответствии с RFC1950.

Сообщение об ошибке для справки: Запись архива была сжата с использованием неподдерживаемого метода сжатия.

Решение состоит в использовании альтернативной библиотеки SharpZipLib.

Вот простой метод, который успешно расшифровал для меня вложение Deflate из файла PDF/A-3:

public static string SZLDecompress(byte[] data) {
    var outputStream = new MemoryStream();
    using var compressedStream = new MemoryStream(data);
    using var inputStream = new InflaterInputStream(compressedStream);
    inputStream.CopyTo(outputStream);
    outputStream.Position = 0;
    return Encoding.Default.GetString(outputStream.ToArray());
}
person Programmierus    schedule 30.04.2020