php 如何能让代码一个一个执行而不占用CPU和内存呢?

wuyutingting 2017-05-19 09:30:43
是这样的,我想遍历网站下的uploads文件夹下多个目录(按日期文件夹存放着图片)里面的图片,可能有5、6千张图片,遍历的时候一个一个的插入到我指定的mysql数据表中,我下面这样写会卡一会,有没有更好的办法或者写法呢?能让程序遍历100条后提示文字,即将继续。。。然后又接着遍历,能做到那样吗?

function traversing($path)
{
$curr = glob($path.'/*');
if($curr)
{
foreach($curr as $f)
{
if(is_dir($f))
{
traversing($f);
}
elseif(strtolower(substr($f, -4))=='.jpg')
{
$dosql->ExecNoneQuery("INSERT INTO `#@__uploads` (path) VALUES ('$f')");
}
elseif(strtolower(substr($f, -4))=='.gif')
{
$dosql->ExecNoneQuery("INSERT INTO `#@__uploads` (path) VALUES ('$f')");
}
elseif(strtolower(substr($f, -4))=='.png')
{
$dosql->ExecNoneQuery("INSERT INTO `#@__uploads` (path) VALUES ('$f')");
}
elseif(strtolower(substr($f, -5))=='.jpeg')
{
$dosql->ExecNoneQuery("INSERT INTO `#@__uploads` (path) VALUES ('$f')");
}
}
}
}

traversing('upload');
...全文
289 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
xuzuning 2017-05-21
  • 打赏
  • 举报
回复
#获取有用到的
select * from uploads a, imgs b where a.path=b,path

#获取没有用到的
select * from uploads a left join imgs b on a.path=b.path where b.id is null 

#获取没有用到的
select * from uploads where path not in (select path from imgs)
wuyutingting 2017-05-20
  • 打赏
  • 举报
回复
引用 4 楼 xuzuning 的回复:
文件太多了! 可用 array_chunk 将数组切成小段,分别处理
array_chunk 不懂怎么切呢,可以让代码休息10秒后继续的办法吗?感觉那样没那么占内存。
xuzuning 2017-05-20
  • 打赏
  • 举报
回复
文件太多了! 可用 array_chunk 将数组切成小段,分别处理
wuyutingting 2017-05-20
  • 打赏
  • 举报
回复
引用 2 楼 xuzuning 的回复:
换个写法,不用递归
function traversing($path) {
$p = array($path); //待遍历的目录
for($i=0; $i<count($p); $i++) {
$p = array_merge($p, glob("{$p[$i]}/*", GLOB_ONLYDIR)); //将本级子目录加入待遍历的目录
$a = preg_grep('/\.(jpeg|jpg|png|gif)/i', glob("{$p[$i]}/*")); //读取本级目录列表,并过滤出图片文件名
$v = join("'),('", $a);
$sql = "INSERT INTO `#@__uploads` (path) VALUES ('$v')"; //构造批量插入指令
    $dosql->ExecNoneQuery($sql);
}
}

在递归写法中,每一层读取的目录列表($curr)所占的内存,要等到本层返回时才会被释放
这显然是很耗内存的
一条条的判断、插入,也不如批量插入来的快

目录文件少的可以,文件多的目录没有遍历进去,这是为什么呢?第一个文件夹的能入库,第二个文件夹的不能入库。





xuzuning 2017-05-20
  • 打赏
  • 举报
回复
换个写法,不用递归
function traversing($path) {
  $p = array($path); //待遍历的目录
  for($i=0; $i<count($p); $i++) {
    $p = array_merge($p, glob("{$p[$i]}/*", GLOB_ONLYDIR)); //将本级子目录加入待遍历的目录
    $a = preg_grep('/\.(jpeg|jpg|png|gif)/i', glob("{$p[$i]}/*")); //读取本级目录列表,并过滤出图片文件名
    $v = join("'),('", $a);
    $sql = "INSERT INTO `#@__uploads` (path) VALUES ('$v')"; //构造批量插入指令
    $dosql->ExecNoneQuery($sql);
  }
}
在递归写法中,每一层读取的目录列表($curr)所占的内存,要等到本层返回时才会被释放 这显然是很耗内存的 一条条的判断、插入,也不如批量插入来的快
jacksq 2017-05-20
  • 打赏
  • 举报
回复
使用预执行SQL,应该会好很多,比如PDO的prepare() <?php $sql="insert into '#@__uploads' (path) values(:file);";//假设$db是外部你的PDO连接对象 $myInsert=$db->conn->prepare($sql); function traversing($path) { $path=realpath($path); if(is_dir($path)){ $file=opendir($path); while($f=readdir($file)){ if($f==='.' || $f==='..') { }else if(is_dir($f)){ traversing("{$path}\\{$f}"); }else{ $pro=strtolower(substr($f, -4)); if(stripos($pro,'.jpg')!==false || stripos($pro,'.gif')!==false || stripos($pro,'.png')!==false){ $myInsert->bindValue(":file",$f); $myInsert->execute(); }else{ $pro=strtolower(substr($f, -5)); if(stripos($pro,'.jpeg')!==false){ $myInsert->bindValue(":file",$f); $myInsert->execute(); } } } } } return true; } traversing('upload'); ?>
wuyutingting 2017-05-20
  • 打赏
  • 举报
回复
引用 6 楼 xuzuning 的回复:
function traversing($path) {
  $p = array($path); //待遍历的目录
  for($i=0; $i<count($p); $i++) {
    $p = array_merge($p, glob("{$p[$i]}/*", GLOB_ONLYDIR)); //将本级子目录加入待遍历的目录
    $a = preg_grep('/\.(jpeg|jpg|png|gif)/i', glob("{$p[$i]}/*")); //读取本级目录列表,并过滤出图片文件名
    foreach(array_chunk($a, 50) as $t) {
      $v = join("'),('", $t);
      $sql = "INSERT INTO `#@__uploads` (path) VALUES ('$v')"; //构造批量插入指令
      $dosql->ExecNoneQuery($sql);
    }
  }
}
这是一次性工作,要休息干什么?
终于可以了,感谢版主。其实我是想做本地图片文件与数据库对比,然后找出不存在的,删除,这样的一个功能。 上次你告诉我将读到的图片名保存到数据库,然后用 sql 指令完成比较。 我现在把本地的所有图片存到数据库uploads表了,与数据库的另一个表imgs表,对比,它们2个表的结构是一样的,只有id 和 path 2个字段。有最快的指令完成比较吗? 我现在是这样比较的 if(!strpos($imgs['path'],$uploads['path'])) { ...//不同的显示在这里。 } 这样的对比我发现感觉也没那么快,还有其他办法吗。
xuzuning 2017-05-20
  • 打赏
  • 举报
回复
function traversing($path) {
  $p = array($path); //待遍历的目录
  for($i=0; $i<count($p); $i++) {
    $p = array_merge($p, glob("{$p[$i]}/*", GLOB_ONLYDIR)); //将本级子目录加入待遍历的目录
    $a = preg_grep('/\.(jpeg|jpg|png|gif)/i', glob("{$p[$i]}/*")); //读取本级目录列表,并过滤出图片文件名
    foreach(array_chunk($a, 50) as $t) {
      $v = join("'),('", $t);
      $sql = "INSERT INTO `#@__uploads` (path) VALUES ('$v')"; //构造批量插入指令
      $dosql->ExecNoneQuery($sql);
    }
  }
}
这是一次性工作,要休息干什么?
komyluo 2017-05-19
  • 打赏
  • 举报
回复
才几千条,先扫描后入库,很快的

21,887

社区成员

发帖
与我相关
我的任务
社区描述
从PHP安装配置,PHP入门,PHP基础到PHP应用
社区管理员
  • 基础编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧