PHP读取目录中的许多文件

时间:2013-09-27 08:01:53

标签: php

我已经看到这个问题已经存在于stackoverflow中,但我的问题没有答案。

我有从其他服务器下载的许多文件的目录,我不知道有多少文件,我认为维度可以是1GB,或者100Mb取决于外部服务器。

现在我已经这样做了:

    ini_set("memory_limit","10000M");
    $directory = "xml_uploads/hotel/";
    $xml_files = glob($directory . "*.xml");       
    foreach($xml_files as $file)
    {
        $content = file_get_contents($file, true);
        $xml = new DOMDocument();
        $xml->loadXML($content);
        if($xml){
           //parse xml and save inside database
        } 
     }

我不知道是否更好的方式在memory_limit中插入一个大数字,因为我不知道相关大小adn如果太大我不想停止我的服务器。 还有另一种解析目录中所有xml文件的方法吗?

由于

3 个答案:

答案 0 :(得分:1)

XML解析

目前您正在使用DOMDocumentfile_get_contents结合使用 - 这意味着您必须首先将巨大的XML文件加载到内存中,并且每当文件大于可用内存时,您将始终达到限制 - 使用下面的解决方案,这不是问题。

如果您关心XML解析代码的内存使用情况,您应该使用pull解析器 - 它是一种XML解析器,它不会将所有内容加载到内存中,但允许您仅在一次只有一个实体 - 这样内存使用量就很小了。在PHP中,您可以使用XML Reader

$xml = new XMLReader();
$xml->open("config.xml");

while ($xml->read()) {
    switch ($xml->name) {
        case "myelem":
             ...
    }
}

大量目录树遍历

当然!有一个DirectoryIteratorRecursiveDirectoryIterator

用法非常相似:

foreach(new DirectoryIterator($directory) as $fileInfo)
{
    if($fileInfo->getExtension() !== 'xml') continue;
    $content = file_get_contents($fileInfo->getPathname(), true);
    ...
}

此外,如果您有嵌套的目录结构,则可以使用另一个:

foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory)) as $fileInfo)
{
    if($fileInfo->getExtension() !== 'xml') continue;
    $content = file_get_contents($fileInfo->getPathname(), true);
    ...
}

请注意,由于此迭代器是递归的,因此我们必须使用RecursiveIteratorIterator包装它;

这两个都可以从PHP 5开始提供(你真的不应该使用下面的任何东西)

答案 1 :(得分:0)

使用下面的代码,您可以获得要上传的文件大小(在上传之前,您将使用js获得文件大小)然后您可以使用ajax上传文件并相应地调整内存大小。

如果不需要,请删除不需要的代码

<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Show File Data</title>
<style type='text/css'>
body {
font-family: sans-serif;
}
</style>
<script type='text/javascript'>
function showFileSize() {
var input, file;

// (Can't use `typeof FileReader === "function"` because apparently
// it comes back as "object" on some browsers. So just see if it's there
// at all.)
if (!window.FileReader) {
bodyAppend("p", "The file API isn't supported on this browser yet.");
return;
}

input = document.getElementById('fileinput');
if (!input) {
bodyAppend("p", "Um, couldn't find the fileinput element.");
}
else if (!input.files) {
bodyAppend("p", "This browser doesn't seem to support the `files` property of file inputs.");
}
else if (!input.files[0]) {
bodyAppend("p", "Please select a file before clicking 'Load'");
}
else {
file = input.files[0];
alert("File " + file.name + " is " + file.size + " bytes in size");

//bodyAppend("p", "File " + file.name + " is " + file.size + " bytes in size");
}
}

function bodyAppend(tagName, innerHTML) {
var elm;

elm = document.createElement(tagName);
elm.innerHTML = innerHTML;
document.body.appendChild(elm);
}
</script>
</head>
<body>
<form action='#' onSubmit="return false;">
<input type='file' id='fileinput'>
<input type='button' id='btnLoad' value='Load' onclick='showFileSize();'>
</form>
</body>
</html>

答案 2 :(得分:0)

Adam的回答已经指出了好的课程,我还有一些提示:

当您执行大量文件和时间/内存消耗时,您无法从浏览器中搜索该脚本。服务器主要具有有限的KeepAlive和Timeout,即使使用1 TB内存也会终止你的脚本。

给你的脚本一个shebang,让它可执行(chmod + x或chmod 700)并从控制台(http://www.php.net/manual/en/features.commandline.usage.php)点击它。

#!/usr/bin/php
<?php
// set memory limit here..
// set time limit:
set_time_limit(0)

// maybe enable garbage collector here
// http://php.net/manual/en/features.gc.php

另见有人遇到类似问题的答案:

php exec() - max_execution_time and Fatal error