我有一个gzip文件,当我在PHP中解压缩数据时,它似乎缺少字符.然而,当我为Python这样做时,字符就出现了.在本例中,缺少最后2个字符("]}"),这使得数据成为无效的JSON.

以下两个示例均输出不同的结果;PHP怎么可能不输出完整的数据?我还判断了GZIP内容,看起来长度和CRC无效;至少当我将 struct 与此站点的数据进行比较时:https://docs.fileformat.com/compression/gz/

<?php

$base64gzip = 'H4sIAAAAAAAAA7XSO04DQAwE0J5jbE3h8d9cJUoRiSPQcXmEFKR4KFKlfdr12Lv+Pp+3r9v5uFwORnTSACTO9f3tUcKfiLbOsFQsEVMxEkwtMRNROtO9b4V0yT5TAcoq5O5QBtkssSeV6LxnSUXWVEKDp5jmDocmNa3e6ZapYJE9OypCWXxXDo0BC2VJKr+qT3AdTXsialw5BHb/5ZBwbRNHWm2C51/aA3n/IwNX9+RJaveE369mcdrOmNFXScdLxKUg64GgkkqLFrz4JjJ+rj/Cx4XMxgMAAB+LCAAAAAAAAAOLrQUAZzx4YAIAAAA=';

echo gzdecode(base64_decode($base64gzip));
#!/usr/bin/python

import gzip
import base64

base64gzip = '''H4sIAAAAAAAAA7XSO04DQAwE0J5jbE3h8d9cJUoRiSPQcXmEFKR4KFKlfdr12Lv+Pp+3r9v5uFwORnTSACTO9f3tUcKfiLbOsFQsEVMxEkwtMRNROtO9b4V0yT5TAcoq5O5QBtkssSeV6LxnSUXWVEKDp5jmDocmNa3e6ZapYJE9OypCWXxXDo0BC2VJKr+qT3AdTXsialw5BHb/5ZBwbRNHWm2C51/aA3n/IwNX9+RJaveE369mcdrOmNFXScdLxKUg64GgkkqLFrz4JjJ+rj/Cx4XMxgMAAB+LCAAAAAAAAAOLrQUAZzx4YAIAAAA='''

print(gzip.decompress(base64.b64decode(base64gzip)))

^^Python输出此数据,包括最后的"]}"字符.

b'{"data":[["190296311161"],\n["190296311154"],\n["190296311154"],\n["190296328299"],\n["190296328275"],\n["190296303203"],\n["190296303197"],\n["190296333002"],\n["190296303883"],\n["190296350870"],\n["190296307515"],\n["190296307164"],\n["190296309168"],\n["190296309151"],\n["190296305863"],\n["075679761255"],\n["190296303982"],\n["190296303975"],\n["190296332784"],\n["190296336621"],\n["190296336607"],\n["190296317552"],\n["190296317545"],\n["190296352591"],\n["190296352584"],\n["190296306297"],\n["190296334955"],\n["190296352263"],\n["190296352263"],\n["190296323584"],\n["190296350139"],\n["5054283041637"],\n["5054283014655"],\n["5054283014648"],\n["5054283014631"],\n["190296350146"],\n["190296306273"],\n["190296310751"],\n["190296310744"],\n["190296315992"],\n["190296315992"],\n["190296315992"],\n["190296315992"],\n["190296315992"],\n["190296315985"],\n["190296315985"],\n["190296315985"],\n["190296315985"],\n["190296315985"],\n["190296340710"],\n["5054283120622"],\n["190296305870"],\n["190296330094"]]}'

有人能告诉我为什么在PHP中这样做会失败,以及我如何确保获得与Python中相同的内容?

推荐答案

您的gzip流有效且正确.它由两个gzip成员组成,每个成员本身都是一个有效的gzip流,第二个仅包含字符]}.Python正确地解码了两个gzip成员,而PHP似乎只解码第一个gzip成员,忽略并默默地丢弃了第二个.

这是PHP gzdecode()中的一个bug,在最新的PHP中似乎仍然存在.

另一种方法是在循环中使用inflate_init()inflate_add()inflate_get_read_len()来读取所有成员.关键是inflate_get_read_len()是到目前为止已使用的gzip流的字节数,使您能够找到下一个gzip成员的开始.下面是我在PHPplayground 上运行的一个示例,其中包含您的数据,以展示我的 idea :

$b64 = 'H4sIAAAAAAAAA7XSO04DQAwE0J5jbE3h8d9cJUoRiSPQcXmEFKR4KFKlfdr12Lv+Pp+3r9v5uFwORnTSACTO9f3tUcKfiLbOsFQsEVMxEkwtMRNROtO9b4V0yT5TAcoq5O5QBtkssSeV6LxnSUXWVEKDp5jmDocmNa3e6ZapYJE9OypCWXxXDo0BC2VJKr+qT3AdTXsialw5BHb/5ZBwbRNHWm2C51/aA3n/IwNX9+RJaveE369mcdrOmNFXScdLxKUg64GgkkqLFrz4JjJ+rj/Cx4XMxgMAAB+LCAAAAAAAAAOLrQUAZzx4YAIAAAA=';
$bin = base64_decode($b64);
$gz = inflate_init(ZLIB_ENCODING_GZIP);
$dec = inflate_add($gz, $bin);
echo inflate_get_status($gz), "\n";
echo inflate_get_read_len($gz), "\n";
echo strlen($dec), "\n";
$used = inflate_get_read_len($gz);
$gz = inflate_init(ZLIB_ENCODING_GZIP);
$dec .= inflate_add($gz, substr($bin, $used));
echo inflate_get_status($gz), "\n";
echo inflate_get_read_len($gz), "\n";
echo strlen($dec), "\n";

这将输出:

1
217
966
1
22
968

其中,1是完整且正确的gzip成员的预期返回码(请确保进行判断),21722是两个gzip成员的长度,966968是解压数据的累积量,第二个表示末尾错误的两个字符被添加.

您可以使用那些没有bug的函数编写自己的gzdecode_complete().

Python相关问答推荐

将DF中的名称与另一DF拆分并匹配并返回匹配的公司

对某些列的总数进行民意调查,但不单独列出每列

try 在树叶 map 上应用覆盖磁贴

"使用odbc_connect(raw)连接字符串登录失败;可用于pyodbc"

如果值发生变化,则列上的极性累积和

如果满足某些条件,则用另一个数据帧列中的值填充空数据帧或数组

未知依赖项pin—1阻止conda安装""

Python逻辑操作作为Pandas中的条件

如何在Python中获取`Genericums`超级类型?

如何在Python中使用另一个数据框更改列值(列表)

如何更改groupby作用域以找到满足掩码条件的第一个值?

如何使regex代码只适用于空的目标单元格

基于形状而非距离的两个numpy数组相似性

matplotlib图中的复杂箭头形状

在不同的帧B中判断帧A中的子字符串,每个帧的大小不同

在二维NumPy数组中,如何 Select 内部数组的第一个和第二个元素?这可以通过索引来实现吗?

使用Python TCP套接字发送整数并使用C#接收—接收正确数据时出错

在Django中重命名我的表后,旧表中的项目不会被移动或删除

一维不匹配两个数组上的广义ufunc

删除另一个div中的特定div容器