【问题标题】:League CSV package - reading one line at a time from a resource/streamLeague CSV 包 - 从资源/流中一次读取一行
【发布时间】:2018-10-16 09:56:56
【问题描述】:

我正在使用 PHP League CSV importer/exporter 在 Laravel 中导入一个大型 CSV 文件。由于文件很大,我想将它流式传输到 CSV 解析器并一次处理一行,而不是将每一行都加载到内存中。

Laravel 使用 flysystem 作为底层文件系统,我正在使用它来获取源 CSV 的 PHP 资源。

我不明白的是,如果可能的话,我如何将该资源流输入到 League CSV,以便它一次读取一行供我处理,然后再读取下一行。所有文档似乎都暗示 CSV 文件总是被完全读入内存,这是我想要避免的。

我需要使用回调吗?如果是这样,我如何确定流资源只根据需要一次读取一行,而不是一次读取?

我猜我是从创建流阅读器开始的?

use League\Csv\Reader;
$reader = Reader::createFromStream($resource, 'r');

【问题讨论】:

    标签: php laravel csv composer-php flysystem


    【解决方案1】:

    您可以使用ReaderIteratorAggregate 接口在不加载整个文件的情况下遍历行。所以你基本上只是这样做

    foreach ($reader as $row) {
        // do stuff
    }
    

    如果您使用 Mac 读取或创建 CSV 文件,则需要将其添加到您的代码中以使其正常工作:

    if (!ini_get("auto_detect_line_endings")) {
        ini_set("auto_detect_line_endings", '1');
    }
    

    【讨论】:

    • 谢谢。运行了一些内存测试后,看起来 CSV 包无论如何都会在内部恢复为资源,即使给定的是本地路径名而不是流或资源。无论您向它扔什么,它都会对IteratorAggregate 进行正确的操作。在foreach 循环超过 40k 长的 CSV 行之后,内存使用量增加了几个 100kbytes,这正是我需要看到的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-10
    • 2018-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多