PHP读取目录中的许多文件

PHP读取目录中的许多文件,php,Php,我已经看到这个问题已经存在于stackoverflow中,但对于我的问题没有答案 我有一个目录,里面有很多从另一台服务器下载的文件,我不知道有多少文件,尺寸是多少,我想可能是1GB,也可能是100Mb,这取决于外部服务器 现在我已经这样做了: ini_set("memory_limit","10000M"); $directory = "xml_uploads/hotel/"; $xml_files = glob($directory . "*.xml");

我已经看到这个问题已经存在于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
        } 
     }
我不知道在内存中插入一个这样的大数字是否更好,因为我不知道rela大小,如果太大,我不想停止我的服务器。 是否存在另一种解析目录中所有xml文件的方法


谢谢

XML解析

目前,您使用的是
DOMDocument
file\u get\u contents
,这意味着您必须首先将庞大的XML文件加载到内存中,并且每当文件大于可用内存时,您总是会达到一个限制-通过下面的解决方案,这不是问题

如果您关心XML解析代码的内存使用情况,那么应该使用
pull
解析器—这是一种XML解析器,它不会将所有内容加载到内存中,但允许您一次只对一个实体进行操作—这样,内存使用就非常少。在PHP中,您可以使用:

大型目录树遍历

当然!有一个和

用法非常相似:

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);
    ...
}
注意,由于这个迭代器是递归的,我们必须用递归迭代器来包装它


这两种方法都是从PHP5开始提供的(您真的不应该使用下面的任何方法)

XML解析

目前,您使用的是
DOMDocument
file\u get\u contents
,这意味着您必须首先将庞大的XML文件加载到内存中,并且每当文件大于可用内存时,您总是会达到一个限制-通过下面的解决方案,这不是问题

如果您关心XML解析代码的内存使用情况,那么应该使用
pull
解析器—这是一种XML解析器,它不会将所有内容加载到内存中,但允许您一次只对一个实体进行操作—这样,内存使用就非常少。在PHP中,您可以使用:

大型目录树遍历

当然!有一个和

用法非常相似:

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);
    ...
}
注意,由于这个迭代器是递归的,我们必须用递归迭代器来包装它


这两种方法都是可用的,因为PHP 5(你真的不应该使用下面的任何东西)

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

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


显示文件数据
身体{
字体系列:无衬线;
}
函数showFileSize(){
var输入,文件;
//(无法使用`typeof FileReader==“function”`因为
//在某些浏览器上,它会以“对象”的形式返回,所以只要看看它是否存在就可以了
//(完全没有。)
如果(!window.FileReader){
bodyAppend(“p”,“此浏览器尚不支持文件API”);
返回;
}
输入=document.getElementById('fileinput');
如果(!输入){
bodyAppend(“p”,“嗯,找不到fileinput元素”);
}
如果(!input.files){
bodyAppend(“p”,“此浏览器似乎不支持文件输入的`files`属性。”);
}
如果(!input.files[0]),则为else{
bodyAppend(“p”,“请在单击“加载”之前选择一个文件”);
}
否则{
file=input.files[0];
警报(“文件”+File.name+”是“+File.size+”字节大小”);
//bodyAppend(“p”,“File”+File.name+”是“+File.size+”字节大小”);
}
}
函数bodyAppend(标记名,innerHTML){
var-elm;
elm=document.createElement(标记名);
elm.innerHTML=innerHTML;
文件.正文.附件(elm);
}

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

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


显示文件数据
身体{
字体系列:无衬线;
}
函数showFileSize(){
var输入,文件;
//(无法使用`typeof FileReader==“function”`因为
//在某些浏览器上,它会以“对象”的形式返回,所以只要看看它是否存在就可以了
//(完全没有。)
如果(!window.FileReader){
bodyAppend(“p”,“此浏览器尚不支持文件API”);
返回;
}
输入=document.getElementById('fileinput');
如果(!输入){
bodyAppend(“p”,“嗯,找不到fileinput元素”);
}
如果(!input.files){
bodyAppend(“p”,“此浏览器似乎不支持文件输入的`files`属性。”);
}
如果(!input.files[0]),则为else{
bodyAppend(“p”,“请在单击“加载”之前选择一个文件”);
}
否则{
file=input.files[0];
警报(“文件”+File.name+”是“+File.size+”字节大小”);
//bodyAppend(“p”,“File”+File.name+”是“+File.size+”字节大小”);
}
}
函数bodyAppend(标记名,innerHTML){
var-elm;
elm=document.createElement(标记名);
elm.innerHTML=innerHTML;
文件.正文.附件(elm);
}

亚当的答案已经指出了好的类,我还有一些提示给你:

当你处理大量文件和耗费时间/内存的事情时,你不能从浏览器中点击该脚本。服务器的KeepAlive和Timeout大部分都是有限的,即使只有1 TB的内存,这也会杀死您的脚本

给脚本一个shebang,使其可执行(chmod+x或chmod 700),然后从控制台()点击它

#/usr/bin/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