在Amazon S3中逐行读取文件?

时间:2011-04-10 21:00:41

标签: amazon-web-services amazon-s3 amazon-ec2 bigdata

是否可以逐行读取Amazon S3的文件?我希望让人们在某处上传大文件,然后让一些代码(可能在亚马逊上运行)逐行读取他们的文件并用它做一些事情,可能是以地图缩减的多线程方式。或者也许只能一次加载1000行......有什么建议吗?

3 个答案:

答案 0 :(得分:1)

Amazon S3确实支持范围请求,但它不是为逐行读取文件而设计的。

然而,看起来Amazon Elastic MapReduce可能非常适合您所寻找的内容。 S3和EC2实例之间的转移将非常快,然后您可以以任何方式分割工作。

答案 1 :(得分:0)

这是PHP中的一个示例代码段,似乎可以执行您所要求的操作(抓取file.txt中的前1000行并连接它们)。这有点懊悔,但这个想法可以用其他语言或其他技术实现。关键是要像对待任何其他文件系统(如windows或linux)一样对待S3,唯一的区别是您使用S3密钥凭据并将文件路径设置为s3://your_directory_tree/your_file.txt“:

<?php 
    set_time_limit(0); 
    include("gs3.php"); 
    /* fake keys!, please put yours */ 
    define('S3_KEY', 'DA5S4D5A6S4D'); 
    define('S3_PRIVATE','adsadasd');

    $f = fopen('s3://mydir/file.txt', 'r');
    $c = "";
    $d = 0;

    $handle = @fopen('s3://mydir/file.txt', "r");
    if ($handle) {
        while (($buffer = fgets($handle)) !== false  && $d < 1000) {
            $c .= $buffer; /* concatenate the string (newlines attached)*/
            $d += 1; /* increment the count*?
        }
        if (!feof($handle)) {
            echo "Error: unexpected fgets() fail\n";
        }
        else{
            print "$c"
        }

        fclose($handle);
    }
?> 

答案 2 :(得分:0)

这是一个使用PHP 7和Laravel 5如何从Amazon S3逐行读取文件的简单示例:

S3StreamReader.php

<?php
declare(strict_types=1);

namespace App\Helpers\Json;

use App\Helpers\S3StreamFactory;
use Generator;
use SplFileObject;

final class S3StreamReader
{
    /**
     * @var \App\Helpers\S3StreamFactory
     */
    private $streamFactory;


    /**
     * @param \App\Helpers\S3StreamFactory $s3StreamFactory
     */
    public function __construct(S3StreamFactory $s3StreamFactory)
    {
        $this->streamFactory = $s3StreamFactory;
    }

    /**
     * @param string $filename
     * @return \Generator
     */
    public function get(string $filename): Generator
    {
        $file = new SplFileObject($this->streamFactory->create($filename), 'r');

        while (!$file->eof()) {
            yield $file->fgets();
        }
    }
}

S3StreamFactory.php

<?php
declare(strict_types=1);

namespace App\Helpers;

use League\Flysystem\AwsS3v3\AwsS3Adapter;

final class S3StreamFactory
{
    /**
     * @var \League\Flysystem\AwsS3v3\AwsS3Adapter
     */
    private $adapter;


    /**
     * @param \League\Flysystem\AwsS3v3\AwsS3Adapter $adapter
     */
    public function __construct(AwsS3Adapter $adapter)
    {
        $this->adapter = $adapter;
        $adapter->getClient()->registerStreamWrapper();
    }

    /**
     * @param string $filename
     * @return string
     */
    public function create(string $filename): string
    {
        return "s3://{$this->adapter->getBucket()}/{$filename}";
    }
}

用法示例:

$lines = (new S3JsonReader(new S3StreamFactory(Storage::disk('s3')->getAdapter())))->get($sourceFile);

while ($lines->valid()) {
    $line = $lines->current();
    // do something with the current line...
    $lines->next();
}

即使您不使用Laravel,您仍然可以使用此代码,因为Laravel仅使用league/flysystem-aws-s3-v3包。