0

0

php如何读取CSV文件内容?php解析与读取CSV数据教程

尼克

尼克

发布时间:2025-09-17 15:25:01

|

919人浏览过

|

来源于php中文网

原创

答案:PHP读取CSV文件的核心是fgetcsv()函数,它可逐行解析并自动处理分隔符和引号;通过file_exists()和fopen()检查文件存在与打开状态,使用循环结合fgetcsv()读取每行数据,最后fclose()关闭句柄;为处理编码问题,可借助mb_convert_encoding()转换源编码至目标编码;针对特殊字符或多行字段,需确保CSV遵循标准格式,fgetcsv()能正确解析被包围符包裹的内容;对于大型文件,应采用逐行处理或生成器避免内存溢出,配合批量操作提升性能。

php如何读取csv文件内容?php解析与读取csv数据教程

PHP读取CSV文件内容的核心在于利用内置的文件操作函数,特别是

fgetcsv()
,它能逐行解析CSV数据,自动处理分隔符和引号,极大地简化了开发工作。

解决方案

说实话,用PHP处理CSV文件,最直接、最常用的方法就是

fgetcsv()
函数。它简直是为这个场景量身定制的。我个人觉得,当你需要从CSV文件里捞数据时,脑子里第一个跳出来的就应该是它。

下面是一个基本的代码示例,展示了如何一步步地读取并解析CSV文件:

 $row) {
        echo "行 " . ($rowIndex + 1) . ": " . implode(' | ', $row) . "\n";
    }
} catch (Exception $e) {
    echo "读取CSV文件时发生错误: " . $e->getMessage() . "\n";
}

?>

这个函数的核心思想就是:打开文件 -> 逐行读取 -> 关闭文件。

fgetcsv()
的第二个参数
length
设置为0,意味着它会读取整行,直到遇到换行符,这对于大多数情况都适用。
delimiter
enclosure
参数则分别定义了字段分隔符和字段包围符,这对于正确解析CSV至关重要。

立即学习PHP免费学习笔记(深入)”;

PHP读取CSV文件时,如何高效处理不同编码格式的数据?

哎,编码问题,这简直是数据处理领域的老大难了。尤其是在处理来自不同系统或地域的CSV文件时,编码不一致是家常便饭。我见过太多因为编码不对导致乱码的情况,那真是让人头疼。

通常,CSV文件可能采用UTF-8、GBK、ISO-8859-1等编码。如果你的PHP脚本默认是UTF-8,而CSV文件是GBK,直接读取出来就会是一堆乱码。

解决方案通常是:识别源文件编码并进行转换

  1. 确定源文件编码

    • 最理想的情况是,你知道CSV文件的原始编码。比如,如果文件是从某个Windows系统导出,很可能是GBK或GB2312。
    • 如果不知道,可以尝试一些编码检测库,比如
      mb_detect_encoding()
      (但它并不总是100%准确,尤其是短文本)。
    • 或者,最笨但有时最有效的方法:用文本编辑器(如Notepad++,VS Code)打开文件,切换编码查看是否显示正常。
  2. 使用

    iconv()
    mb_convert_encoding()
    进行转换
    : 一旦确定了源编码,就可以在读取每一行数据后,对每个字段进行编码转换。

     $row) {
    //         echo "行 " . ($rowIndex + 1) . ": " . implode(' | ', $row) . "\n";
    //     }
    // } catch (Exception $e) {
    //     echo "读取CSV文件时发生错误: " . $e->getMessage() . "\n";
    // }
    ?>

    这里,我们把源编码和目标编码作为参数传入,这样灵活性就大大提高了。记住,如果源文件编码和你的脚本编码一致,就没必要转换了,避免不必要的性能开销。

    PHP与MySQL程序设计3
    PHP与MySQL程序设计3

    本书是全面讲述PHP与MySQL的经典之作,书中不但全面介绍了两种技术的核心特性,还讲解了如何高效地结合这两种技术构建健壮的数据驱动的应用程序。本书涵盖了两种技术新版本中出现的最新特性,书中大量实际的示例和深入的分析均来自于作者在这方面多年的专业经验,可用于解决开发者在实际中所面临的各种挑战。 本书内容全面深入,适合各层次PHP和MySQL开发人员阅读,既是优秀的学习教程,也可用作参考手册。

    下载

PHP处理包含特殊字符或多行内容的CSV字段,有哪些实用技巧?

CSV格式,全称是逗号分隔值,听起来简单,但实际操作起来,那些特殊字符和多行内容可真是让人头疼。

fgetcsv()
在处理这些情况时,其实已经做了很多工作,但我们作为开发者,还是得了解它的机制。

核心技巧在于理解CSV的包围符(Enclosure)规则。

  1. 包围符的作用: 当一个字段本身包含分隔符(比如逗号)、换行符或者包围符自身时,这个字段就需要用包围符(通常是双引号

    "
    )包起来。 例如:
    "Hello, World"
    ,
    "This is a multi-line\nfield"

  2. fgetcsv()
    如何处理包围符
    fgetcsv()
    函数设计之初就考虑到了这一点。只要你的CSV文件遵循标准的CSV格式(RFC 4180),
    fgetcsv()
    就能正确解析。

    • 包含分隔符的字段
      fgetcsv()
      会自动识别被包围符包起来的字段,即使里面有分隔符,也不会被错误地分割。 例如:
      "Apple, Banana",Orange
      会被解析为
      ["Apple, Banana", "Orange"]
    • 包含换行符的字段(多行内容):如果一个字段被包围符包起来,并且内部含有换行符,
      fgetcsv()
      会把整个被包围的内容作为一个字段来处理,直到找到匹配的结束包围符。 例如:
      "First line\nSecond line",Value2
      会被解析为
      ["First line\nSecond line", "Value2"]
    • 包围符自身作为数据:如果字段内部需要包含包围符本身,那么这个包围符需要被双写(Escaped)。 例如:
      "He said ""Hello!"" to me"
      会被解析为
      ["He said \"Hello!\" to me"]
      fgetcsv()
      会自动把双写的包围符还原成单个包围符。
  3. 实用技巧

    • 明确
      enclosure
      参数
      :确保
      fgetcsv()
      $enclosure
      参数与你的CSV文件实际使用的包围符一致。默认是双引号
      "
      ,这在绝大多数情况下都适用。
    • 生成CSV时遵循标准:如果你也需要生成CSV文件,务必遵循这些规则。使用
      fputcsv()
      函数是最好的选择,它会自动帮你处理字段的包围和转义。
    • 数据清洗:尽管
      fgetcsv()
      处理得很好,但有时原始数据可能会有不规范的地方。读取后,你可能还需要对数据进行进一步的
      trim()
      (去除首尾空白)、
      stripslashes()
      (如果数据源有额外的斜杠转义)等操作,确保数据的干净和一致性。

我个人经验是,只要CSV文件是“规矩”生成的,

fgetcsv()
几乎不会出问题。但如果数据源本身就不规范,比如有些字段该加引号没加,那再好的解析器也无能为力,这时候就得考虑源头数据清洗或者更复杂的自定义解析逻辑了。

PHP读取大型CSV文件时,如何优化性能并防止内存溢出?

处理小型CSV文件,前面的方法绰绰有余。但如果你的CSV文件动辄几十兆、上百兆甚至几个G,一次性把所有数据读到内存里,那内存溢出(

Allowed memory size of X bytes exhausted
)的错误就等着你了。这种时候,我们必须改变策略,采用流式处理的思想。

核心思路是:逐行处理,不将整个文件加载到内存

  1. fgetcsv()
    的天然优势: 其实,
    fgetcsv()
    函数本身就是为逐行读取设计的。它每次只读取一行数据到内存,处理完当前行后,内存就可以被释放或重用,而不会积累。这是它处理大型文件而不导致内存溢出的关键。

    // 示例中 readCsvFile 函数就是逐行读取的,所以它本身就具有内存优化的特性。
    // $data[] = $row; 这一步会把所有行都存起来,
    // 如果你只是想处理数据而不存储,可以这么改:
    function processLargeCsvFile(string $filePath, callable $rowProcessor, string $delimiter = ',', string $enclosure = '"')
    {
        // ... 文件存在和打开的检查 ...
        $handle = fopen($filePath, 'r');
        if ($handle === false) { /* ... */ }
    
        while (($row = fgetcsv($handle, 0, $delimiter, $enclosure)) !== false) {
            // 不把所有行都存到 $data 数组里
            // 而是直接处理当前行
            $rowProcessor($row); // 调用一个回调函数来处理每一行
        }
        fclose($handle);
    }
    
    // 使用示例:
    // processLargeCsvFile('large_data.csv', function($row) {
    //     // 这里可以对 $row 进行数据库插入、计算、日志记录等操作
    //     // 确保每次处理完一行,相关的内存占用都能被释放
    //     echo "处理行: " . implode(', ', $row) . "\n";
    // });

    通过这种方式,

    $data
    数组就不会无限增长,从而避免了内存溢出。

  2. PHP生成器(Generators): 对于PHP 5.5及更高版本,生成器是一个非常优雅的解决方案。它允许你编写一个函数,像迭代器一样逐个生成值,而不是一次性返回一个完整的数组。这在处理大型数据集时,能够显著减少内存占用。

     $row) {
    //         // 每次循环只加载一行数据到内存
    //         // 可以在这里进行数据库插入、数据转换等操作
    //         // echo "处理行 " . ($rowIndex + 1) . ": " . implode(' | ', $row) . "\n";
    //     }
    // } catch (Exception $e) {
    //     echo "读取CSV文件时发生错误: " . $e->getMessage() . "\n";
    // }
    ?>

    生成器让代码看起来更简洁,同时保持了内存效率。

  3. unset()
    变量: 如果你在循环内部创建了临时变量,并且这些变量可能会占用较大内存,处理完后及时
    unset()
    它们是一个好习惯。虽然PHP的垃圾回收机制会处理,但手动
    unset()
    可以更早地释放内存。

  4. 调整PHP的

    memory_limit
    : 这更像是一个“治标不治本”的方案,但有时也是必要的。在
    php.ini
    中或者在脚本开头使用
    ini_set('memory_limit', '512M');
    来增加PHP脚本可用的内存上限。不过,这不能解决根本问题,如果文件真的非常大,你最终还是会遇到限制。我个人觉得,优化代码结构才是王道,调整
    memory_limit
    只是一个辅助手段。

  5. 批量处理(Batch Processing): 如果你需要将CSV数据导入数据库,不要每读取一行就执行一次数据库插入。这会导致大量的数据库连接和I/O操作,效率极低。更好的做法是,每读取N行数据(例如1000行),就批量执行一次数据库插入。这样可以显著提高性能。

    // 简单的批量插入示例
    // $batchSize = 1000;
    // $batch = [];
    // foreach (getCsvRowsGenerator('large_data.csv') as $row) {
    //     $batch[] = $row;
    //     if (count($batch) >= $batchSize) {
    //         // 执行批量数据库插入操作
    //         // insertIntoDatabase($batch);
    //         $batch = []; // 清空批次
    //     }
    // }
    // if (!empty($batch)) {
    //     // 处理剩余的批次
    //     // insertIntoDatabase($batch);
    // }

综合来看,

fgetcsv()
配合逐行处理或生成器,是PHP处理大型CSV文件最有效且内存友好的方法。避免一次性加载所有数据,是防止内存溢出的金科玉律。

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

2748

2023.09.01

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

1676

2023.10.11

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

1536

2023.10.11

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

995

2023.10.23

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

1464

2023.10.23

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

1235

2023.11.03

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1549

2023.11.09

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1307

2023.11.13

html编辑相关教程合集
html编辑相关教程合集

本专题整合了html编辑相关教程合集,阅读专题下面的文章了解更多详细内容。

38

2026.01.21

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 9.1万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 9.5万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 0.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号