使用PHP将大体积TXT转换为结构化JSON出现内存溢出问题求解
问题根源
你当前的实现存在两个核心高内存占用点:
- 用
file_get_contents一次性将完整大文件加载到内存,文件体积超过内存限额就会直接触发报错 - 所有键值对全部存储到PHP数组中,最后一次性执行
json_encode,数组运行时占用的内存会远高于原始文本本身的体积
可行解决方案
核心思路是流式读取+流式写入,全程不将完整文件和全量数组加载到内存:
<?php // 甚至不需要调高内存限额,128M完全足够 ini_set('memory_limit', '128M'); function txt_to_json_stream_converter($sep1, $sep2, $input_file, $output_file) { // 只读模式打开输入文件流 $in_handle = fopen($input_file, 'r'); if (!$in_handle) die("Unable to open input file..."); // 只写模式打开输出文件流,先写入JSON起始大括号 $out_handle = fopen($output_file, 'w'); if (!$out_handle) die("Unable to open output file..."); fwrite($out_handle, '{'.PHP_EOL); $first_item = true; $buffer = ''; // 循环读取文件流直到结束 while (!feof($in_handle)) { // 每次读取1024字节到缓冲区,可根据实际情况调整大小 $buffer .= fread($in_handle, 1024); // 拆分缓冲区中完整的键值对片段 while (($sep_pos = strpos($buffer, $sep1)) !== false) { $item = substr($buffer, 0, $sep_pos); $buffer = substr($buffer, $sep_pos + strlen($sep1)); // 拆分键和值,加参数2避免值中包含分隔符时拆分错误 list($key, $val) = explode($sep2, $item, 2); // 处理JSON格式逗号,第一个键值对前不加逗号 if (!$first_item) { fwrite($out_handle, ','.PHP_EOL); } $first_item = false; // 转义后直接写入当前键值对到输出文件 fwrite($out_handle, ' '.json_encode($key).':'.json_encode($val)); } } // 处理缓冲区剩余的最后一个键值对 if (!empty($buffer)) { list($key, $val) = explode($sep2, $buffer, 2); if (!$first_item) { fwrite($out_handle, ','.PHP_EOL); } fwrite($out_handle, ' '.json_encode($key).':'.json_encode($val).PHP_EOL); } // 写入JSON结束大括号 fwrite($out_handle, '}'.PHP_EOL); fclose($in_handle); fclose($out_handle); echo 'Done!'; } txt_to_json_stream_converter("-", ">", "my_exported_data.txt", "structured_data.json"); ?>
方案优势
- 内存占用稳定在KB级别,无论输入文件多大都不会出现内存溢出问题
- 不需要修改PHP配置调高内存限额,兼容低配运行环境
- 处理速度和原始一次性读取方案差异极小,磁盘IO是主要性能瓶颈
内容的提问来源于stack exchange,提问作者user17348055
相关产品推荐
相关产品推荐

