【问题标题】:Recovering data from a corrupted, possibly partial zip从损坏的、可能是部分 zip 中恢复数据
【发布时间】:2023-02-05 20:51:27
【问题描述】:

我正在使用一些旧的遗留代码并遇到一些构建错误。我有一个名为 vocab100k.zip 的 zip 文件,代码表明它应该解压缩以包含 2 个文件:vocab.100k.utf8vectors.100k.utf8

当我尝试运行System.IO.Compression.ZipFile.OpenRead(zipFileFullPath) 时,我得到System.IO.InvalidDataException: 'End of Central Directory record could not be found.' 当我尝试使用 WinRAR 通过文件资源管理器手动解压缩时,我得到“意外的存档结束”。

双击预览内容显示我的两个文件之一存在于其中。

我使用了 WinRAR 的修复功能,但在修复后的 zip 上尝试提取将在它抛出以下错误之前加载到大约 90%。

我怀疑这在某个时候可能是一个多部分压缩包之一,后来的压缩包已经丢失了。有什么方法可以提取我在那里看到的 vectors.100k.utf8 的一部分吗? zip 是否有其他可能被破坏的方式?

【问题讨论】:

  • zip 文件 vocab100k.zip 是否公开供我们查看?
  • @pmqs 不幸的是,这是一些专有的工作数据:(
  • 好的明白。在这种情况下,如果您安装了 Perl 或可以访问 Linux 系统(或者甚至在您的 Windows 设置上运行了 WSL),您可以获取 github.com/pmqs/zipdetails/blob/main/bin/zipdetails 的副本并运行此命令 perl zipdetails --scan -v vocab100k.zip。这将转储仍然存在于 zip 文件中的 zip 元数据的详细信息。请张贴那个。它将提供有关 zip 文件损坏程度的更多信息。

标签: zip unzip winrar


【解决方案1】:

从截断的 Zip 文件中恢复数据

假设文件只是在vectors.100k.utf8 中间被截断并且损坏并不严重,您应该能够恢复部分数据。您显示的输出确实表明这是一个截断问题。如果没有我请求的 zipdetails 输出,我将无法确定。

如果这只是一个截断问题,您可以解压缩下面的 perl 脚本 recoverzip 中存在的内容。这应该适用于 Windows、MacOS 或 Linux——唯一的先决条件是您需要安装 perl

use strict ;
use warnings ;

use IO::Uncompress::Unzip qw( unzip $UnzipError );

die "Usage: recoverzip zipfile member outfile
"
    if @ARGV != 3;

my $filename = shift;
my $name = shift;
my $outfile = shift;

unzip $filename  => $outfile,
           Name  => $name,
    or die "Cannot uncompress '$filename': $UnzipError
" ;

该脚本接受三个参数

  • 要处理的 zip 文件的名称
  • 要读取的 zip 成员的名称
  • 存储恢复数据的输出文件名

此脚本不能保证从截断的 zip 文件中获取任何数据,但在某些情况下可以。这仅取决于截断的位置。

创建截断的 zip 文件

这是一个工作示例,展示它是如何工作的。请注意,我正在使用 Linux 工具生成截断的 zip 文件。恢复部分不依赖于 Linux——只需要在您的系统上安装perl

首先选择一个输入文件以添加到 zip 文件

$ cat lorem.txt
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
in reprehenderit in voluptate velit esse cillum dolore eu fugiat
nulla pariatur. Excepteur sint occaecat cupidatat non proident,
sunt in culpa qui officia deserunt mollit anim id est laborum.

lorem.txt 添加到名为 try.zip 的 zip 文件中

$ zip try.zip lorem.txt
$ unzip -l try.zip 
Archive:  try.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
      446  2022-09-09 09:17   lorem.txt
---------                     -------
      446                     1 file

现在我们需要在lorem.txt成员的中间截断try.zip。为此,我们需要了解压缩数据在 zip 文件中的位置。可以使用zipdetails 获取该信息。

$ perl zipdetails try.zip

0000 LOCAL HEADER #1       04034B50
0004 Extract Zip Spec      14 '2.0'
0005 Extract OS            00 'MS-DOS'
0006 General Purpose Flag  0000
     [Bits 1-2]            0 'Normal Compression'
0008 Compression Method    0008 'Deflated'
000A Last Mod Time         55294A2E 'Fri Sep  9 10:17:28 2022'
000E CRC                   F90EE7FF
0012 Compressed Length     0000010E
0016 Uncompressed Length   000001BE
001A Filename Length       0009
001C Extra Length          001C
001E Filename              'lorem.txt'
0027 Extra ID #0001        5455 'UT: Extended Timestamp'
0029   Length              0009
002B   Flags               '03 mod access'
002C   Mod Time            631AF698 'Fri Sep  9 09:17:28 2022'
0030   Access Time         631AF698 'Fri Sep  9 09:17:28 2022'
0034 Extra ID #0002        7875 'ux: Unix Extra Type 3'
0036   Length              000B
0038   Version             01
0039   UID Size            04
003A   UID                 000003E8
003E   GID Size            04
003F   GID                 000003E8
0043 PAYLOAD

0151 CENTRAL HEADER #1     02014B50
0155 Created Zip Spec      1E '3.0'
0156 Created OS            03 'Unix'
0157 Extract Zip Spec      14 '2.0'
0158 Extract OS            00 'MS-DOS'
0159 General Purpose Flag  0000
     [Bits 1-2]            0 'Normal Compression'
015B Compression Method    0008 'Deflated'
015D Last Mod Time         55294A2E 'Fri Sep  9 10:17:28 2022'
0161 CRC                   F90EE7FF
0165 Compressed Length     0000010E
0169 Uncompressed Length   000001BE
016D Filename Length       0009
016F Extra Length          0018
0171 Comment Length        0000
0173 Disk Start            0000
0175 Int File Attributes   0001
     [Bit 0]               1 Text Data
0177 Ext File Attributes   81ED0000
017B Local Header Offset   00000000
017F Filename              'lorem.txt'
0188 Extra ID #0001        5455 'UT: Extended Timestamp'
018A   Length              0005
018C   Flags               '03 mod access'
018D   Mod Time            631AF698 'Fri Sep  9 09:17:28 2022'
0191 Extra ID #0002        7875 'ux: Unix Extra Type 3'
0193   Length              000B
0195   Version             01
0196   UID Size            04
0197   UID                 000003E8
019B   GID Size            04
019C   GID                 000003E8

01A0 END CENTRAL HEADER    06054B50
01A4 Number of this disk   0000
01A6 Central Dir Disk no   0000
01A8 Entries in this disk  0001
01AA Total Entries         0001
01AC Size of Central Dir   0000004F
01B0 Offset to Central Dir 00000151
01B4 Comment Length        0000
Done

zipdetails 有很多输出,但出于我们的目的,我们需要查看PAYLOAD 行——它显示了lorem.txt 的压缩数据开始的偏移量。在这种情况下,它是十六进制 043。下一个字段是 CENTRAL HEADER,偏移量为十六进制 0151。这意味着压缩的有效负载从偏移量 0x43 开始,到 0x150 结束。

现在截断位于lorem.txt 压缩数据中间偏移量 0x100 处的 zip 文件,并将截断的 zip 文件写入 trunc.zip

$ head -c $((0x100)) try.zip >trunc.zip

我们现在有一个示例截断的 zip 文件来测试。首先检查unzip 对截断文件的看法 - 它显示的错误与您的错误非常相似

$ unzip -t trunc.zip 
Archive:  trunc.zip
  End-of-central-directory signature not found.  Either this file is not
  a zipfile, or it constitutes one disk of a multi-part archive.  In the
  latter case the central directory and zipfile comment will be found on
  the last disk(s) of this archive.
unzip:  cannot find zipfile directory in one of trunc.zip or
        trunc.zip.zip, and cannot find trunc.zip.ZIP, period.

从截断的 zip 文件中恢复数据

现在运行 recoverzip 脚本,看看我们是否可以从 zip 文件中获取任何数据。

$ perl recoverzip trunc.zip lorem.txt recovered.txt
Cannot uncompress 'trunc.zip': unexpected end of file

unexpected end of file 错误在这个用例中是意料之中的。

最后,让我们看看恢复了哪些数据

$ cat recovered.txt 
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
in reprehenderit in voluptate velit e

成功!在这种情况下,我们已经从lorem.txt 恢复了一些数据。

【讨论】:

    【解决方案2】:

    如果你可以访问 Linux,你可以尝试使用 zip 工具来创建存档的固定版本:

    zip -FF vocab100k.zip --out vocab100k_fixed.zip
    

    但这仅在您要提取的文件不缺少任何部分的情况下才有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多