任意语言实现读取压缩包注释

前言:用记事本打开压缩包有惊喜。。

首先需要了解一下什么是压缩包注释,为什么要使用压缩包注释

压缩包注释

本质类似RAR+JPG(知乎),就是在压缩包后面追加一堆文本

这些文本就是注释了

由此可见,压缩包注释并不是一种规范,但是大多数压缩软件在生成压缩包的时候都可以携带注释

为什么使用压缩包注释

1.注释本体不会被压缩,可以直接读取

2.压缩软件可以查看和生成注释,生成注释很方便(推荐一下好压2.7老版,挺良心的)

3.使用注释不会影响压缩的文件

实现读取

(均以PHP+7Z压缩包为例)

我们可以采取一种低成本的解决方案,即在我们需要的注释开始结束时,用特定的字符串标记,比如:

<!——START-MOECRAFT-PACKAGE-INFO——>
程序可读的文本…
<!——END-MOECRAFT-PACKAGE-INFO——>

这样,程序在搜索到开头和结尾的两个字符串的时候,就可以知道哪些是注释了

举例:

$buffer=file_get_contents(‘mods.7z’); //读入整个文件
$sp = strpos($buffer, ‘<!——START-MOECRAFT-PACKAGE-INFO——>’); //搜索开头
if($sp !== false) {
$ep = strpos($buffer, ‘<!——END-MOECRAFT-PACKAGE-INFO——>’); //搜索结尾
echo iconv(‘gb2312’,’utf-8’,substr($buffer, $sp , $ep)); //截取字符串并输出。由于压缩软件生成的注释编码可能是GB2312,这里需要转码
}

但是,这个代码有致命的问题

因为压缩包可能会非常大,直接读入整个文件到内存是愚蠢的

因此我们需要对代码稍作修改

$fp = fopen(‘mods.7z’,’r’);
while (($buffer = fread($fp, 10485760)) !== false) { //一次读取10485760byte
$sp = strpos($buffer, ‘<!——START-MOECRAFT-PACKAGE-INFO——>’);
$ep = strpos($buffer, ‘<!——END-MOECRAFT-PACKAGE-INFO——>’);
if($sp !== false && $ep !== false) { //一般情况: 读取到了注释开头和结尾
echo iconv(‘gb2312’,’utf-8’,substr($buffer, $sp , $ep)); //截取字符串并输出。由于压缩软件生成的注释编码可能是GB2312,这里需要转码
break; //直接停止循环
} elseif($sp !== false && $ep === false) { //特殊情况:找到了注释开头但是找不到结尾
echo iconv(‘gb2312’,’utf-8’,substr($buffer, $sp));
break;
} elseif($sp === false && $ep !== false) { //特殊情况:找到了注释结尾但是找不到开头
echo iconv(‘gb2312’,’utf-8’,substr($buffer, 0, $ep));
break;
}
}
fclose($fp);

不要以为这个代码也没问题

虽然解决了上面的内存占用问题,但是我们得考虑一种罕见的情况:

开头标识或结尾标识被“切”了

这样就压根找不到注释了,目前我只有下面的解决方案:

1.对于根本不可能打开很大的压缩包的场景,直接用第一条的代码,简单省事。

2.注释开头标识和结尾标识不要太长,越短越好

3.对于可能打开大压缩包的场景,一次读取的内容多一些

 

乱码问题迟迟无法解决?有种东西叫Base64

 

码字真累