如何读取zip压缩包内的单个文件

44

我需要读取zip文件中的单个文件"test.txt"的内容。整个zip文件是一个非常大的文件(2gb),包含了很多文件(10,000,000),因此无法将整个zip文件解压缩为可行的解决方案。那么我该如何读取单个文件?


12
这个问题其实并不愚蠢。我在搜索“使用PHP从ZIP文件中提取一个文件”时进入了这里。很奇怪它被投票踩了。 - ivkremer
2个回答

64

尝试使用zip://包装器

$handle = fopen('zip://test.zip#test.txt', 'r'); 
$result = '';
while (!feof($handle)) {
  $result .= fread($handle, 8192);
}
fclose($handle);
echo $result;

你也可以使用file_get_contents

$result = file_get_contents('zip://test.zip#test.txt');
echo $result;

2
它还可以处理文件,例如$content=file('zip://test.zip#test.txt'); - Emil Borconi
3
@Sami:phar:// 包装器似乎支持此操作。可以使用 file_get_contents('phar://yourfile.tar.gz/path/to/file.txt'); 进行访问。参见:https://dev59.com/X2445IYBdhLWcg3wZJiw#4878849 - gen_Eric
@RocketHazmat,它一直在加载:)。此外,我使用“tar -tf i.tar.gz”检查了文件,路径没有问题。 - Sami
1
@RocketHazmat - 你有没有想过如何使用远程 https 文件来完成这个任务? - Scott Paterson
@ScottPaterson:我没有测试过,但是file_get_contents('zip://https://example.com/test.zip#test.txt');会起作用吗?否则,您可能需要先将文件下载到内存(或临时文件夹)中。 - gen_Eric
显示剩余6条评论

4
请注意@Rocket-Hazmat的fopen解决方案可能会导致无限循环,如果zip文件受密码保护,因为fopen将失败,并且feof无法返回true。 您可能需要将其更改为
$handle = fopen('zip://file.zip#file.txt', 'r');
$result = '';
if ($handle) {
    while (!feof($handle)) {
        $result .= fread($handle, 8192);
    }
    fclose($handle);
}
echo $result;

这解决了无限循环的问题,但如果您的zip文件受到密码保护,则可能会看到类似以下的内容:

警告:file_get_contents(zip:// file.zip#file.txt):无法打开流:操作失败

不过,有一个解决办法:
从PHP 7.2开始,新增支持加密文件。
所以您可以像下面这样同时使用file_get_contentsfopen函数。
$options = [
    'zip' => [
        'password' => '1234'
    ]
];

$context = stream_context_create($options);
echo file_get_contents('zip://file.zip#file.txt', false, $context);

如果担心加密压缩文件,而想在读取前检查文件是否存在,则更好的解决方案是使用 ZipArchive

$zip = new ZipArchive;
if ($zip->open('file.zip') !== TRUE) {
    exit('failed');
}
if ($zip->locateName('file.txt') !== false) {
    echo 'File exists';
} else {
    echo 'File does not exist';
}

这将起作用(无需知道密码)

注意:要使用 locateName 方法查找文件夹,您需要像 folder/ 一样通过在末尾添加斜杠传递它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接