PHP 读取/导出 CSV 文件

在工作中, 经常会遇到导入/导出的需求。以下是常用的 PHP 方法, 用于读取 CSV 文件和导出 CSV 文件

读取 CSV 文件

该方法可以分页读取 CSV 文件, 通过设置读取行数和起始行数来控制读取的范围

/**
 * 读取 CSV 文件
 * @param string $csv_file   CSV 文件路径
 * @param int $lines         读取的行数
 * @param int $offset        起始行数, 从文件的第几行开始读取
 * @return array|bool
 */
public function read_csv_lines($csv_file = '', $lines = 0, $offset = 0)
{
    if (!$fp = fopen($csv_file, 'r')) {
        return false;
    }
    $i = $j = 0;
    // 跳过前 $offset 行
    while (false !== ($line = fgets($fp))) {
        if ($i++ < $offset) {
            continue;
        }
        break;
    }
    $data = array();
    // 读取接下来的 $lines 行数据
    while (($j++ < $lines) && !feof($fp)) {
        $data[] = fgetcsv($fp);
    }
    fclose($fp);
    return $data;
}

导出 CSV 文件

导出 CSV 文件可以通过两种方法实现

方法 1: 简单导出 CSV

方法通过简单的输出流导出数据, 每次将数据行直接输出

/**
 * 导出 CSV 文件
 * @param array $data          数据
 * @param array $header_data   首行数据
 * @param string $file_name    文件名称
 * @return string
 */
public function export_csv_1($data = [], $header_data = [], $file_name = '')
{
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename=' . $file_name);
    
    // 输出表头数据
    if (!empty($header_data)) {
        echo iconv('utf-8', 'gbk//TRANSLIT', '"' . implode('","', $header_data) . '"') . "\n";
    }
    
    // 输出数据
    foreach ($data as $key => $value) {
        $output = array();
        $output[] = $value['id'];
        $output[] = $value['name'];
        echo iconv('utf-8', 'gbk//TRANSLIT', '"' . implode('","', $output) . "\"\n");
    }
}

方法 2: 分页导出 CSV

方法则分批输出数据, 以防止内存溢出, 每隔一定行数刷新输出缓冲区, 适用于数据量较大的导出

/**
 * 导出 CSV 文件
 * @param array $data          数据
 * @param array $header_data   首行数据
 * @param string $file_name    文件名称
 * @return string
 */
public function export_csv_2($data = [], $header_data = [], $file_name = '')
{
    header('Content-Type: application/vnd.ms-excel');
    header('Content-Disposition: attachment;filename=' . $file_name);
    header('Cache-Control: max-age=0');
    
    // 打开输出流
    $fp = fopen('php://output', 'a');
    
    // 输出表头数据
    if (!empty($header_data)) {
        foreach ($header_data as $key => $value) {
            $header_data[$key] = iconv('utf-8', 'gbk', $value);
        }
        fputcsv($fp, $header_data);
    }

    // 分批输出数据
    $num = 0;
    // 每隔 $limit 行刷新一次输出缓冲区, 不要太大, 也不要太小
    $limit = 100000;
    // 逐行取出数据, 不浪费内存
    $count = count($data);
    
    if ($count > 0) {
        for ($i = 0; $i < $count; $i++) {
            $num++;
            
            // 刷新输出缓冲区, 防止数据过多造成内存溢出
            if ($limit == $num) {
                ob_flush();
                flush();
                $num = 0;
            }

            // 处理当前行数据
            $row = $data[$i];
            foreach ($row as $key => $value) {
                $row[$key] = iconv('utf-8', 'gbk', $value);
            }
            fputcsv($fp, $row);
        }
    }
    fclose($fp);
}

原文

PHP 读取/导出 CSV文件

最后更新于 2021-08-07
使用 Hugo 构建
主题 StackJimmy 设计