当前位置:首页 > PHP教程 > php文件操作 > 列表

PHP处理JSON Lines文件怎么读写

发布:smiling 来源: PHP粉丝网  添加日期:2026-10-13 10:51:45 浏览: 评论:0 

JSON Lines文件不能用json_decode(file_get_contents($file)),因为其每行是独立JSON值而非单个JSON对象,整文件解析会语法错误;须逐行读取并解码。

JSON Lines文件读取时为什么不能用 json_decode(file_get_contents($file))

因为 JSON Lines(.jsonl)不是单个 JSON 对象,而是每行一个独立的 JSON 值(对象、数组、字符串等),整文件直接 json_decode() 会失败,报错类似 JSON_ERROR_SYNTAX 或只解析第一行就终止。

正确做法是逐行读取 + 逐行解码:

用 file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) 一次性读入所有非空行(适合小到中等文件)

或用 fopen() + fgets() 流式读取(推荐,内存友好,适合大文件)

对每一行调用 json_decode($line, true);注意检查返回值是否为 null,并用 json_last_error() 判断是否解析失败

示例片段:

  1. if ($fp = fopen('data.jsonl', 'r')) { 
  2.     while (($line = fgets($fp)) !== false) { 
  3.         $line = trim($line); 
  4.         if ($line === '') continue; 
  5.         $data = json_decode($line, true); 
  6.         if ($data === null && json_last_error() !== JSON_ERROR_NONE) { 
  7.             error_log("JSON parse error on line: " . $line); 
  8.             continue; 
  9.         } 
  10.         // 处理 $data... 
  11.     } 
  12.     fclose($fp); 
  13. } 

写入 JSON Lines 文件时 json_encode() 的关键参数

每行必须是严格合法的 JSON 文本,且行尾不能有多余空格或换行符。常见错误是忘记 PHP_EOL 或误加逗号、括号。

每次写入前确保数据可被 json_encode() 序列化(无资源、无循环引用)

推荐加上 JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES 避免中文转义、URL 中斜杠被转义

必须手动追加 PHP_EOL(Windows 下是 "\r\n",但用 PHP_EOL 更安全)

不要用 file_put_contents($file, $json . PHP_EOL, FILE_APPEND) 循环写——频繁磁盘 I/O 慢;改用 fopen(..., 'a') + fwrite()

示例:

  1. $fp = fopen('output.jsonl', 'a'); 
  2. foreach ($rows as $row) { 
  3.     $json = json_encode($row, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); 
  4.     if ($json === false) { 
  5.         error_log("JSON encode failed: " . json_last_error_msg()); 
  6.         continue; 
  7.     } 
  8.     fwrite($fp, $json . PHP_EOL); 
  9. } 
  10. fclose($fp); 

遇到中文乱码或特殊字符解析失败怎么办

JSON Lines 规范要求 UTF-8 编码,但 PHP 默认不校验输入编码。如果文件含 BOM 或混入 GBK 字节,json_decode() 会静默失败(返回 null)。

排查和修复步骤:

用 mb_detect_encoding($line, ['UTF-8', 'GBK'], true) 检查单行编码;若非 UTF-8,先 mb_convert_encoding($line, 'UTF-8', 'GBK')

用 hexdump -C file.jsonl | head 查看前几字节,确认无 EF BB BF(UTF-8 BOM);如有,需 ltrim($line, "\xEF\xBB\xBF")

json_last_error_msg() 返回 "Malformed UTF-8 characters" 就基本锁定编码问题

大文件处理时性能瓶颈在哪、怎么绕过

真正卡住的往往不是 JSON 解析本身,而是 I/O 和内存:一次 file() 读几百 MB 文件会爆内存;反复 fgets() 在机械硬盘上慢;json_decode() 对超长嵌套结构(如深度 > 512)也会变慢。

实用优化点:

用 stream_set_read_buffer($fp, 0) 关闭读缓冲(某些场景反而更快)

避免在循环里做日志输出或数据库插入;攒批处理(例如每 100 行 commit 一次)

对已知结构的数据,考虑用 json_decode($line, false, 512, JSON_BIGINT_AS_STRING) 控制深度和大整数处理

极端情况(GB 级)可结合 pcntl_fork() 分块读取,但要注意进程间文件指针不共享,得按字节偏移切分

最常被忽略的是:没关掉 Xdebug。开发环境开着 Xdebug 解析 10 万行 JSONL,速度可能差 5–10 倍。

Tags: JSON文件怎么读写 PHP文件怎么读写

分享到: