美文网首页
php导出百万数据生成csv 2024-05-10

php导出百万数据生成csv 2024-05-10

作者: 阿然学编程 | 来源:发表于2024-05-09 13:37 被阅读0次
//生成器减少内存占用
function chunk_iterator(iterable $iterable, int $size): Generator
{
    if ($size > 0) {
        $chunk = [];
        $count = 0;

        foreach ($iterable as $item) {
            $chunk[] = $item;
            $count++;
            if ($count === $size) {
                yield $chunk;
                $chunk = [];
                $count = 0;
            }
        }

        if ($chunk) {
            yield $chunk;
        }
    } else {
        // 当 $size 为0时,直接逐个yield每个元素
        foreach ($iterable as $item) {
            yield $item;
        }
    }
}


function chunk_iterator(iterable $iterable, int $size): Generator
{
    if ($size <= 0) {
        foreach ($iterable as $item) {
            yield $item;
        }
        return;
    }

    $chunk = [];
    $count = 0;
    foreach ($iterable as $item) {
        $chunk[] = $item;
        $count++;
        if ($count === $size) {
            yield $chunk;
            $chunk = []; // 重置块,释放内存
            $count = 0;  // 重置计数器
        }
    }

    // 处理最后不足 $size 的部分
    if ($count > 0) {
        yield $chunk;
    }
}

function exportToCsv($filename, array $header, iterable $data, int $chunkSize = 10000)
{
    // 设置合理的内存限制和执行时间限制
    set_time_limit(0);
    ini_set('memory_limit', '1024M');

    // 配置响应头以便于文件下载
    header('Content-Type: text/csv; charset=utf-8');
    header('Content-Disposition: attachment; filename="' . $filename . '.csv"');
    header('Cache-Control: no-cache, max-age=0');
    header('Pragma: no-cache');

    // 使用输出流开始写入CSV
    $handle = fopen('php://output', 'w');

    // 决定是否写入UTF-8 BOM(根据实际需求调整)
    fwrite($handle, "\xEF\xBB\xBF");

    // 写入列标题
    fputcsv($handle, $header);

    $lineCount = 0;

    // 分块写入数据并适时刷新缓冲区
    foreach (iterator_to_array(chunk_iterator($data, $chunkSize)) as $chunk) {

        foreach ($chunk as $item) {

            foreach ($item as $k => $v) {

                if (preg_match('/\d+/', $v) || is_numeric($v) && strlen($v) > 15) {
                    //数字或超过15位加"\t"防止数据失真乱码
                    $item[$k] = "\t" . $v;
                }

            }

            if (fputcsv($handle, $item)) {
                $lineCount++;
            }

            // 每达到指定行数刷新缓冲区
            if ($lineCount % $chunkSize === 0) {
                // 刷新输出缓冲,提高性能
                ob_flush();
                flush();
            }
        }
    }

    // 关闭输出流
    fclose($handle);

    // 正常结束脚本
    exit();
}
  • 使用示例
$data = Db::table('testhz')->field('配送员,配送区,日期')->select();
exportToCsv('test', ['日期', '配送区', '日期'], $data);

相关文章

网友评论

      本文标题:php导出百万数据生成csv 2024-05-10

      本文链接:https://www.haomeiwen.com/subject/kfqsfjtx.html