在PHP中解析Zipped(GZ)JSON文件


Parsing a Zipped (GZ) JSON file in PHP

在Stackoverflow上的帮助下,我现在可以从文件中解析JSON代码,并将"值"保存到数据库中

然而,我打算从中读取的文件实际上是一个巨大的2GB文件。我的web服务器将无法保存此文件。然而,它将持有一个ZIPPED版本,即80MB。(即GZ)

我相信有一种方法可以从ZIPPED文件(.GZ)中解析JSON……有人能帮忙吗?

我已经找到了下面的函数,我相信它会做到这一点(我想),但我不知道如何将其链接到我的代码

private function uncompressFile($srcName, $dstName) {
$sfp = gzopen($srcName, "rb");
$fp = fopen($dstName, "w");
while ($string = gzread($sfp, 4096)) {
fwrite($fp, $string, strlen($string));
}
gzclose($sfp);
fclose($fp);
}

下面是我当前的PHP代码,并且可以正常工作。它读取一个基本的小文件,JSON对其进行解码(JSON在一系列单独的行中,因此需要file_IGNORE_NEW_lines),然后取一个值并保存到MySQL数据库。

然而,我认为我需要以某种方式将这两位代码结合起来,这样我就可以在不超过网络服务器上100MB存储空间的情况下读取ZIPPED文件

$file="CIF_ALL_UPDATE_DAILY_toc-update-sun";
$trains = file($json_filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($trains as $train) {
$json=json_decode($train,true);
foreach ($json as $key => $value) {
$input=$value['main_train_uid'];
$q="INSERT INTO railstptest (main_train_uid) VALUES ('$input')";
$r=mysqli_query($mysql_link,$q);
}
}   
}   
if (is_null($json)) {
die("Json decoding failed with error: ". json_last_error());
}
mysqli_close($mysql_link);

非常感谢

编辑

下面是JSON的一个简短片段。有一系列

我只想得到几个关键值。例如值G90491和P20328。很多信息我不需要

{"JsonAssociationV1":{"transaction_type":"Delete","main_train_uid":"G90491","assoc_train_uid:"G90525","assoc_start_date":"2013-09-07T00:00Z","location":"EDINBUR","base_location_suffix":null,"diagram_type":"T","CIF_stp_indicator":"O"}{"JsonAssociationV1":{"transaction_type":"Delete","main_train_uid":"P20328","assoc_train_uid":"P21318","assoc_start_date":"2013-08-23T00:00:00Z","location":

可以对文件进行流提取,然后使用流JSON解析器。ZipArchivegetStream,有人为PHP创建了一个流式JSON解析器。

您必须编写一个监听器,在找到数据库值时插入这些值,并丢弃不必要的JSON,这样就不会消耗内存。

$zip = new ZipArchive;
$zip->open("file.zip");
$parser = new JsonStreamingParser_Parser($zip->getStream("file.json"),
    new DB_Value_Inserter);
$parser->parse();

根据您的问题,您使用的是gzip而不是zip。要获得流,您可以使用

fopen("compress.zlib://path/to/file.json", "r");

编写DB_Value_Inserter很困难,因为您还没有提供所需的JSON格式,但似乎您可以重写Listener::value方法,只编写您收到的字符串值。

PHP有压缩包装器,可以帮助打开和读取压缩文件中的行。一个是用于读取gzip文件:

$gzipFile = 'CIF_ALL_UPDATE_DAILY_toc-update-sun.gz';
$trains = new SplFileObject("compress.zlib://{$gzipFile}", 'r');
$trains->setFlags(SplFileObject::DROP_NEW_LINE | SplFileObject::READ_AHEAD
    | SplFileObject::SKIP_EMPTY);

因为SplFileObject是可迭代的,所以可以保持外部foreach循环的原样。当然,fgets()仍然是使用SplFileObject的替代方案。