Читать файл построчно в Amazon S3? - PullRequest
2 голосов
/ 11 апреля 2011

Можно ли построчно читать файл с Amazon S3?Я хочу позволить людям загружать большие файлы куда-нибудь, а затем иметь некоторый код (возможно, работающий на Amazon), построчно читать их файлы и что-то делать с ними, возможно, многопоточным способом с уменьшенным числом карт.Или может быть просто возможность загружать 1000 строк одновременно ... Есть предложения?

Ответы [ 3 ]

1 голос
/ 11 апреля 2011

Amazon S3 поддерживает запросы диапазона, но не предназначен для построчного чтения файла.

Тем не менее, похоже, что Amazon Elastic MapReduce вполне подойдет для того, что вы ищете. Переводы между S3 и используемыми экземплярами EC2 будут очень быстрыми, и тогда вы сможете разделить работу любым удобным вам способом.

0 голосов
/ 23 июня 2018

Вот простой пример, использующий 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 .

0 голосов
/ 12 апреля 2011

Вот пример фрагмента в PHP, который, кажется, выполняет то, что вы просите (захватывает первые 1000 строк в файле file.txt и объединяет их). Это немного капризно, но идея может быть реализована на других языках или с использованием других методов. Ключ должен относиться к S3 так же, как к любой другой файловой системе, такой как windows или linux, с той лишь разницей, что вы используете свои учетные данные ключей 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);
    }
?> 
...