【问题标题】:C# decode (decompress) Deflate data of PDF FileC# decode(解压) PDF File的Deflate数据
【发布时间】:2012-02-08 16:44:53
【问题描述】:

我想在 C# 中解压缩一些 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);
    }
}

有人有什么想法吗? 谢谢。

【问题讨论】:

  • 为什么前两个字节不相关?
  • 流解码器使用 RFC1951。与 DeflateStreams 结合使用时,前两个字节无关紧要。如果流解码器使用的是 RC1950,那么我也必须使用第一个字节。
  • 你做了什么来证明错误是不正确的并且数据实际上是有效的。

标签: c# deflate compression


【解决方案1】:

您需要做的就是使用 GZip 而不是 Deflate。下面是我在 PDF 文档中用于流... endstream 部分内容的代码:

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

        }

【讨论】:

    【解决方案2】:
    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 让我走上正轨!只需将流的所有字节传递给上述函数的输入。确保字节数与指定的长度相同。

    【讨论】:

      【解决方案3】:

      我为测试数据添加了这个:-

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

      没有错误。

      我的结论是前两个字节是相关的(显然它们与我的特定测试数据有关。)或 你的数据有问题。

      我们可以使用您的一些测试数据吗?

      (如果它很敏感,显然不要)

      【讨论】:

        【解决方案4】:

        对于 PDF/A-3 文档中的 Deflate 附件,没有任何解决方案适合我。一些研究表明,.NET DeflateStream 不支持根据 RFC1950 带有标头和尾标的压缩流。

        参考错误消息:存档条目是使用不受支持的压缩方法压缩的。

        解决方案是使用替代库SharpZipLib

        这是一个简单的方法,它为我成功地从 PDF/A-3 文件中解码了 Deflate 附件:

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

        【讨论】:

          猜你喜欢
          • 2017-11-08
          • 2011-09-06
          • 2018-06-16
          • 1970-01-01
          • 2022-01-19
          • 1970-01-01
          • 2016-01-06
          • 2011-03-02
          • 1970-01-01
          相关资源
          最近更新 更多