使用aws-php-sdk从s3存储桶中读取csv.gz文件。所有的文件都是csv.gz文件,我计划读取这些文件,然后将数据导入我的数据库。
我已经查看了许多堆栈溢出问题,但似乎无法使其正常工作。
以下是我到目前为止编写的代码。
$s3 = new S3Client([
'version' => 'latest',
'region' => 'us-east-2',
'credentials' => [
'key' => '',
'secret' => ''
]
]);
$s3->registerStreamWrapper();
if ($stream = fopen('s3://bucket/file.csv.gz', 'r')) {
// While the stream is still open
while (!feof($stream)) {
// Read 1024 bytes from the stream
$d = gzread($stream, 1024);
var_dump($d);
}
// Be sure to close the stream resource when you're done with it
fclose($stream);
}下面的代码只是返回随机字符的加载,这些字符必须是压缩文件的内容。
如果有人可以分享如何解压缩csv.gz文件,然后从它读取的代码示例,允许我将其导入到数据库中,我将不胜感激。
发布于 2021-08-10 07:26:33
对于在将来的搜索中输入此主题的任何人:
我尝试使用哈姆雷特关于使用stream_filter_append的答案,但注意到我的一些机器在这个解决方案中有问题(尽管流仍然是打开的,并且并不是所有的数据都被读取了,但是fread返回了0字节读取。
我遇到了this thread --原来在php中有一个用于流缓冲的已知bug。使用我写这篇文章的帖子中的代码,它可能会帮助下一个穿越这些路径的旅行者:
// init $client from S3Client
$client->registerStreamWrapper();
// full s3 path to the file
$gzipUrl = "s3://{$bucketName}/{$filePath}";
$sourceFile = fopen($gzipUrl, 'rb');
$targetFile = fopen(sys_get_temp_dir() . '/user_input_import.csv.gz', 'wb');
stream_copy_to_stream($sourceFile, $targetFile);
fclose($sourceFile);
fclose($targetFile);
copy('compress.zlib://' . sys_get_temp_dir() . '/user_input_import.csv.gz', $tmpFileName);对于我的项目来说,它起到了作用。
发布于 2020-10-12 02:44:09
为了让gzread正常工作,你必须用gzopen打开文件。但是gzopen不支持文件流,所以使用这个功能,你只能通过提供相应的文件路径来打开位于服务器上的文件。
在您的情况下,解决方案将是使用压缩过滤器。所以你必须使用fopen来打开文件流,然后应用压缩流过滤器来读取.gz解码的数据。
stream_filter_append(
$stream,
'zlib.inflate',
STREAM_FILTER_READ,
["window" => 32]
);有关详细信息,请参阅文档:https://www.php.net/manual/en/filters.compression.php
不幸的是,上面的文档中没有足够的关于window参数的信息。下面是来自zlib.h inflateInit2文档的更有用的信息:
windowBits参数是最大窗口大小(历史记录缓冲区的大小)的以2为底的对数。对于此版本的库,它应该在8..15范围内。如果使用inflateInit,则默认值为15。
..。
对于可选的gzip解码,windowBits也可以大于15。在windowBits中添加32以启用zlib和gzip解码并自动检测报头,或者添加16以仅解码gzip格式( zlib格式将返回Z_DATA_ERROR)。如果正在对gzip流进行解码,则strm->adler是CRC-32而不是Adler-32。与gunzip实用程序和gzread() (见下文)不同,inflate()不会自动解码连接的gzip流。
inflate()将在gzip流的末尾返回Z_STREAM_END。该状态将需要被重置以继续解码后续的gzip流。
基于这个信息,我建议使用窗口大小32,因为这个大小将支持带有自动报头检测的zlib和gzip解码。
所以最终的代码应该是这样的:
$s3 = new S3Client([
'version' => 'latest',
'region' => 'us-east-2',
'credentials' => [
'key' => '',
'secret' => '',
],
]);
$s3->registerStreamWrapper();
if ($stream = fopen('s3://bucket/file.csv.gz', 'r')) {
stream_filter_append(
$stream,
'zlib.inflate',
STREAM_FILTER_READ,
["window" => 32]
);
// While the stream is still open
while (!feof($stream)) {
// Read 1024 bytes from the stream
$d = gzread($stream, 1024);
var_dump($d);
}
// Be sure to close the stream resource when you're done with it
fclose($stream);
}https://stackoverflow.com/questions/62677088
复制相似问题