首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PHP S3流包装器读取CSV GZ压缩文件

PHP S3流包装器读取CSV GZ压缩文件
EN

Stack Overflow用户
提问于 2020-07-01 20:40:02
回答 2查看 461关注 0票数 0

使用aws-php-sdk从s3存储桶中读取csv.gz文件。所有的文件都是csv.gz文件,我计划读取这些文件,然后将数据导入我的数据库。

我已经查看了许多堆栈溢出问题,但似乎无法使其正常工作。

以下是我到目前为止编写的代码。

代码语言:javascript
复制
$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文件,然后从它读取的代码示例,允许我将其导入到数据库中,我将不胜感激。

EN

回答 2

Stack Overflow用户

发布于 2021-08-10 07:26:33

对于在将来的搜索中输入此主题的任何人:

我尝试使用哈姆雷特关于使用stream_filter_append的答案,但注意到我的一些机器在这个解决方案中有问题(尽管流仍然是打开的,并且并不是所有的数据都被读取了,但是fread返回了0字节读取。

我遇到了this thread --原来在php中有一个用于流缓冲的已知bug。使用我写这篇文章的帖子中的代码,它可能会帮助下一个穿越这些路径的旅行者:

代码语言:javascript
复制
        // 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);

对于我的项目来说,它起到了作用。

票数 1
EN

Stack Overflow用户

发布于 2020-10-12 02:44:09

为了让gzread正常工作,你必须用gzopen打开文件。但是gzopen不支持文件流,所以使用这个功能,你只能通过提供相应的文件路径来打开位于服务器上的文件。

在您的情况下,解决方案将是使用压缩过滤器。所以你必须使用fopen来打开文件流,然后应用压缩流过滤器来读取.gz解码的数据。

代码语言:javascript
复制
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解码。

所以最终的代码应该是这样的:

代码语言:javascript
复制
$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);
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62677088

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档