【问题标题】:Parsing large file using php linux server使用 php linux 服务器解析大文件
【发布时间】:2012-06-21 22:54:12
【问题描述】:

我是一名 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 scripting..etc)。

【问题讨论】:

  • 你是如何进行解析的?
  • 您应该重新表述您的问题到底想要什么。如果想按模式拆分文件 - 问这个。如果您需要有关内存映射文件的建议 - 询问这个。以上内容有点……混乱。
  • 我正在使用 file_get_contents 并对整个数据进行 preg_match。

标签: php linux perl file shell


【解决方案1】:

... 1500 MB 的内存限制肯定表明你已经偏离了轨道。

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

您可能会尝试使用更多类似 C(但仍然是 PHP)的结构,特别是 fopen()fseek()fread()。如果文件是带有换行符的已知结构,您也可以考虑fgets()

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

请注意,在 PHP(或任何其他语言)中,您还必须潜在地考虑字符串编码的问题,因为通常情况下,1 字节 == 1 字符(参见.Unicode)。

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

【讨论】:

  • 感谢您的回复。是的,我使用的是 file_get_contents()。我会尝试使用 fgets。
【解决方案2】:

您实际上可以一次用 PHP 解析 XML 一个小块,因此您实际上根本不需要太多内存:

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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-24
    • 1970-01-01
    • 2013-10-21
    • 1970-01-01
    • 2013-09-13
    • 1970-01-01
    相关资源
    最近更新 更多