【问题标题】:Unzip a file with a particular extension (not .zip)解压缩具有特定扩展名的文件(不是 .zip)
【发布时间】:2018-07-25 05:50:14
【问题描述】:

如何解压下载的压缩文件(使用 Deflate 方法压缩,ANSI 编码)具有以下文件特征

  • 动态扩展(例如 .23U 或 .23M)
  • 使用 Deflate 方法压缩和 ANSI 编码
  • 可以通过 7-Zip 作为存档打开,但打开解压缩后仍然无法阅读

以及以下技术要点

  • 以任何方式使用 DeflateStream 都不起作用
  • 使用 GZipStream 是为了 .gz
  • DotNetZip 库经常被推荐,但它太重而无法引用该项目(并且没有真正记录)

在另一个 c++ 项目中(我实际上需要模仿 C# 中的行为),使用了一个 dunzip.dll 库并导致可读字符。 我们可以在网上看到有一个dunzip32.dll用于C#的库,但是没有关于如何使用它的文档。

编辑:

这是我从压缩文件中获得的字节数组的前 100 个字节(十进制):

80 75 3 4 20 0 8 0 8 0 67 75 79 76 0 0 0 0 0 0 0 0 0 0 0 0 12 0 0 0 50 50 67 67 48 48 48 49 46 50 51 85 204 189 117 88 85 251 215 238 77 9 2 210 221 157 210 221 221 221 139 142 69 119 119 119 119 119 119 119 135 32 8 136 10 38 2 10 38 138 138 29 32 234 59 231 210 189 55 107 242 187 246 251 158 115 158 231 60 239 255

这是我得到的100个十六进制前字节的报告:

0000-0010:  50 4b 03 04-14 00 08 00-08 00 60 4b-47 4c 00 00  PK...... ..`KGL..
0000-0020:  00 00 00 00-00 00 00 00-00 00 0c 00-00 00 32 32  ........ ......22
0000-0030:  43 43 30 30-30 31 2e 32-33 55 cc bd-75 58 55 fb  CC0001.2 3U..uXU.
0000-0040:  d7 ee 4d 09-02 d2 dd 9d-d2 dd dd dd-8b 8e 45 77  ..M..... ......Ew
0000-0050:  77 77 77 77-77 77 87 20-08 88 0a 26-02 0a 26 8a  wwwwww.. ...&..&.
0000-0060:  8a 1d 20 ea-3b e7 d2 bd-37 6b f2 bb-f6 fb 9e 73  ....;... 7k.....s
0000-0064:  9e e7 3c ef                                      ..<.

它以 50 4b 03 04 开头的事实意味着它是一种基于 zip 的格式: 然后,将其视为一个 zip 文件,我尝试使用 msdn 示例中的简单方法解压缩数据,在一种情况下使用 MemoryStream,在另一种情况下使用 FileStream。

public static string UnzipString3(byte[] byteArrayCompressedContent)
{
    using (var outputStream = new MemoryStream())
    {
        using (var compressStream = new MemoryStream(byteArrayCompressedContent))
        {
            using (var deflateStream = new DeflateStream(compressStream, CompressionMode.Decompress))
            {
                deflateStream.CopyTo(outputStream);
            }
        }
        return Encoding.UTF8.GetString(outputStream.ToArray());
    }
}


public void UnzipProperZipFile()
{
        try
        {
            using (var outputStream = new MemoryStream())
            {
                FileInfo fileInfo = new FileInfo("NormalZip.zip");
                FileStream fileStream = fileInfo.OpenRead();
                fileStream.Position = 2;
                using (var deflateStream = new DeflateStream(fileStream, CompressionMode.Decompress))
                {
                    deflateStream.CopyTo(outputStream);
                }
                string res = Encoding.UTF8.GetString(outputStream.ToArray());
            }
        }
        catch (Exception e)
        {
            Console.WriteLine("errorlole");
        }
}

在这两种情况下,它都会给出“块长度与其补码不匹配”错误。但是,这是 Microsoft 推荐的方法,它应该以这种方式工作。 我意识到如果我消耗前两个字节,它不会给出那个错误,而是会导致一个空字符串......

编辑:

我显然在使用“正确”的 zip 文件时遇到了同样的问题(即使其他人已经成功使用了相同的算法),所以我将尝试使用外部解压缩库。

编辑

它与 Lasse Vågsæther Karlsen 建议的 Class ZipArchive 一起使用,他的代码在解压后获取数据方面的工作效率是 10/10。 现在剩下的就是能够拥有可理解的数据。我实际上对数据了解不多,除了:

  • 记事本告诉我它是 ANSI 编码的

当我在提取文件后在 MemoryStream 中传输数据时,我会尝试以所有使用的编码来获取它;

entryStream.CopyTo(memoryStream);
string laChaineUTF8 = Encoding.UTF8.GetString(memoryStream.ToArray());
string laChaineDefault = Encoding.Default.GetString(memoryStream.ToArray());
string laChaineUnicode = Encoding.Unicode.GetString(memoryStream.ToArray());
string laChaineASCII = Encoding.ASCII.GetString(memoryStream.ToArray());
string laChaineBigEndianUnicode = Encoding.BigEndianUnicode.GetString(memoryStream.ToArray());
string laChaineUTF7 = Encoding.UTF7.GetString(memoryStream.ToArray());
string laChaineUTF32 = Encoding.UTF32.GetString(memoryStream.ToArray());

它们都没有给出可以理解的字符链。

【问题讨论】:

  • 在读取数据时扩展并不重要。只要文件是解压器能理解的格式。
  • 这不是您在 SO 上提出此类问题的方式。您需要示例输入(文件、字符串)、到目前为止尝试过的代码(即使不工作)以及预期的输出。
  • 我仍然不太确定该文件是只是扩展名已更改的 zip 文件还是完全不同的压缩格式。如果本质上是一个 zip 文件,System.IO.Compression.ZipFile 有什么问题?
  • 顺便说一句:如果您的文件格式不是真正的 zip,而是一些自定义压缩,那么通过从 C# 桥接到本机 dunzip.dll来利用唯一的工作软件怎么样>?
  • 但是如果这是一个 zip 文件,为什么不使用任何 zip 归档类来处理它呢? zip 文件格式不仅仅是简单的压缩数据。试试ZipArchive 类。

标签: c# archive unzip compression deflate


【解决方案1】:

问题在于 .ZIP 文件不仅仅是简单的压缩数据。有目录结构、校验和、文件元数据等。

您需要使用了解此结构的类。除非该文件使用了一些更高级的东西,例如加密和跨存档,否则 .NET ZipArchive 类可能会解决问题。

这是一个从 zip 存档中提取文本文件内容的简单程序。您必须根据自己的需要对其进行调整:

using (var file = File.Open(@"D:\Temp\Temp.zip", FileMode.Open))
using (var archive = new ZipArchive(file))
{
    var entry = archive.GetEntry("ttt/README.md");
    using (var entryStream = entry.Open())
    using (var memory = new MemoryStream())
    {
        entryStream.CopyTo(memory);
        Console.WriteLine(Encoding.UTF8.GetString(memory.ToArray()));
    }
}

【讨论】:

  • 谢谢!它直接起作用。我实际上在想,既然它是一种 deflate 压缩方法,那么使用 DeflateStream 将是合适的。现在我知道这是一种通用的压缩方式。
  • 嗯,其实你可以使用deflate解压来解压文件,你只需要在zip文件中找到压缩后的数据,这就是其他结构的全部内容。
猜你喜欢
  • 1970-01-01
  • 2010-10-28
  • 2020-01-07
  • 2012-02-14
  • 1970-01-01
  • 2018-12-22
  • 2018-10-21
  • 1970-01-01
  • 2020-11-30
相关资源
最近更新 更多