在PHP中解析压缩(GZ)JSON文件

在PHP中解析压缩(GZ)JSON文件,php,json,decode,unzip,Php,Json,Decode,Unzip,在Stackoverflow的帮助下,我现在可以解析文件中的JSON代码,并将的“值”保存到数据库中 然而,我打算读取的文件实际上是一个巨大的2GB文件。我的web服务器将无法保存此文件。然而,它将拥有它的压缩版本——ie 80MB 我相信有一种方法可以解析压缩文件(.GZ)中的JSON……有人能帮忙吗 我已经找到了下面的函数,我相信它可以做到这一点(我想),但我不知道如何将它链接到我的代码 private function uncompressFile($srcName, $dstName)

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

然而,我打算读取的文件实际上是一个巨大的2GB文件。我的web服务器将无法保存此文件。然而,它将拥有它的压缩版本——ie 80MB

我相信有一种方法可以解析压缩文件(.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在一系列单独的行中,因此需要文件\忽略\新建\行),然后获取一个值并保存到MySQL数据库

不过,我相信我需要以某种方式将这两位代码结合起来,这样我就可以在不超过Web服务器上100MB存储空间的情况下读取压缩文件

$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”:{“事务类型”:“删除”,“主要列车uid”:“G90491”,“关联列车uid”:“G90525”,“关联开始日期”:“2013-09-07T00:00:00Z”,“位置”:“爱丁堡”,“基本位置后缀”:null,“图表类型”:“T”,“CIF\stp指示器”:“O”} {“JsonAssociationV1”:{“事务类型”:“删除”,“主列uid”:“P20328”,“关联列uid”:“P21318”,“关联开始日期”:“2013-08-23T00:00:00Z”,“位置”:“marybn”,“基本位置后缀”:null,“图表类型”:“T”,“CIF\U stp指示器”:“C”}

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);

因为它是可编辑的,所以您可以保持外部
foreach
循环的原样。当然,它仍然是使用
SplFileObject

的替代方法,可以对文件进行流提取,然后使用流JSON解析器
ZipArchive
getStream
,还有人

您必须编写一个侦听器,在找到数据库值时插入这些值,并丢弃不必要的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\u Value\u Inserter
很困难,因为您没有提供所需的JSON格式,但似乎您可以重写
Listener::Value
方法,只编写收到的字符串值。

所以这是一个.ZIP文件,而不是.GZ(gzip)文件?不提取就无法解析。这对压缩数据不起作用。json文件没有单独行的概念。@hakre:在原始代码中,每行都被解码为一个完全独立的json字符串。因此,整个文件不必一次存储在内存中。只需回答一个小问题:“我相信有一种方法可以解析压缩文件中的JSON,而无需实际保存2GB版本的文件”-你为什么这么认为?(实际上,Stackoverflow是关于编程问题,而不是关于倾向于信条的信仰)。(这同样适用于对你的进一步信任,但如果你只是第一次回答,我很好)谢谢你,谢谢。它适用于较小的.GZ文件,但80MB压缩文件的内存不足。这会是web服务器内存不足吗?@user2635961:您收到了什么错误消息?至少在PHP5.4.6上,我还没有成功地重现内存泄漏。PleaseStand:对于许多循环来说,它运行良好。然后重复说有一个警告:为foreach()提供的参数无效,最后出现致命错误:内存不足(已分配65798144)(尝试分配65014721字节)……脚本在JSON的.GZ小文件上运行良好。当我把它应用到更大的文件时。我想我需要一次读一行。我还应该补充一点,我正在通过IE10浏览器运行脚本。请注意:除此之外,浏览器在URL中显示一个断页。我已经编辑了一段JSON。你是对的。我只会在JSON中查找一些值。很多JSON 95%都是不需要的。您可以提供任何帮助,因为我对PHP非常陌生。我正在使用一个.GZ文件。感谢有没有一种逐行读取和解析JSON的方法(你会看到这个结构可以做到这一点)——即只在内存中保留JSON的当前行?谢谢