使用 php Linux 服务器解析大文件


Parsing large file using php linux server

我是一名php程序员,目前我正在处理文件。我必须解析数据并将其插入 mysql 数据库。由于其大量的数据php无法加载或解析文件。即使我已将memory_limit增加到 1500MB,我也会收到内存泄漏错误。

    FATAL:  emalloc():  Unable to allocate 456185835 bytes

我的文本文件包含文本和 XML 数据。我必须从文本文件中解析 xml 数据。

    eg: <ajax>some text goes here</ajax> non relativ text <ajax>other content</ajax>

在上面的例子中,我必须解析标签内的内容。如果有人能给出一些建议,将每个标签分成单独的文件(例如:1.txt,2.txt),那就太好了(perl或c或shell脚本)。等)。

...1500 MB 内存限制是您偏离轨道的明确迹象。

您从哪里获得文件? 我假设(给定大小)这是一个本地文件。 如果您尝试使用 file_get_contents() 将文件加载到字符串中,值得注意的是文档是错误的,并且所述函数实际上并未使用内存映射的 I/O(参见错误 52802)。 所以这对你不起作用。

你可以尝试的是回退到更像C(但仍然是PHP)的结构,特别是fopen()fseek()fread()。 如果文件是带有换行符的已知结构,则还可以考虑使用 fgets()

这些应该允许您将字节以块的形式读取到合理大小的缓冲区中,您可以从中进行处理。 由于看起来您正在处理标记的字符串,因此您将不得不玩保留多个缓冲区的常规游戏,您可以在其中积累数据直到可处理。 这是大多数介绍中涵盖的相当标准的内容,例如,C 中的流处理。

请注意,在PHP(或任何其他语言)中,您还必须考虑字符串编码问题,因为一般来说,1字节== 1个字符(参见Unicode)不再是这种情况。

正如你暗示的那样,PHP 可能不是完成此任务的最佳语言(尽管它肯定可以做到这一点)。 但是你的问题并不是一个特定于语言的问题;您遇到了在没有内存映射的情况下处理大文件的基本限制。

你实际上可以用PHP一次解析一小块XML,所以你实际上根本不需要太多的ram:

set_time_limit(0);
define('__BUFFER_SIZE__', 131072);
define('__XML_FILE__', 'pf_1360591.xml');
function elementStart($p, $n, $a) {
  //handle opening of elements
}
function elementEnd($p, $n) {
  //handle closing of elements
}
function elementData($p, $d) {
  //handle cdata in elements
}
$xml = xml_parser_create();
xml_parser_set_option($xml, XML_OPTION_TARGET_ENCODING, 'UTF-8');
xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
xml_set_element_handler($xml, 'elementStart', 'elementEnd');
xml_set_character_data_handler($xml, 'elementData');
$f = fopen(__XML_FILE__, 'r');
if($f) {
  while(!feof($f)) {
    $content = fread($f, __BUFFER_SIZE__);
    xml_parse($xml, $content, feof($f));
    unset($content);
  }
  fclose($f);
}