【问题标题】:php file list array into array treephp 文件列表数组转换成数组树
【发布时间】:2014-11-22 23:05:13
【问题描述】:

我有一些元素数量超过 100 的文件列表数组,我需要将其转换为树数组并将它们插入数据库并在调用时返回树以用于 json api 目录系统 我花了一周时间尝试不同的算法,但它们都在某个时候失败了。 这是数组:

$files[] = array('dir1/dir2/dir3/file1.mkv', 44444);
$files[] = array('dir1/dir2/dir3/file2.mkv', 44444);
$files[] = array('dir1/dir2/file1.mkv', 44444);
$files[] = array('dir1/dir2/file2.txt', 11111);
$files[] = array('dir1/file1.exe', 22222);
$files[] = array('dir1/file2.exe', 22222);
$files[] = array('file1.rar', 3333);

第一个元素是文件路径,第二个元素是文件大小。 这些文件在此服务器上不存在,它们在不同的服务器上,这是 api 服务器。 我需要将它转换成这样的嵌套树数组:

Array
(
    [dir1] => Array
        (
            [dir2] => Array
                (
                    [dir3] => Array
                    (
                        [0] => Array
                            (
                                [name] => file1.mkv
                                [size] => 44444
                            )

                        [1] => Array
                            (
                                [name] => file2.mkv
                                [size] => 44444
                            )

                    )

                    [0] => Array
                        (
                            [name] => file1.mkv
                            [size] => 44444
                        )

                    [1] => Array
                        (
                            [name] => file2.txt
                            [size] => 11111
                        )

                )

            [0] => Array
                (
                    [name] => file1.exe
                    [size] => 22222
                )

            [1] => Array
                (
                    [name] => file2.exe
                    [size] => 22222
                )

        )

    [0] => Array
        (
            [name] => file1.rar
            [size] => 3333
        )

)

我写了一些代码,但它只升到第 2 级 (dir2),然后在第 3 级 (dir3) 上,它无法按预期执行。

代码:

foreach ($files as $file)
{
    $info = pathinfo($file[0]);
    if ($info['dirname'] != '.')
    {
        if (strpos($info['dirname'], '/') !== false)
        {
            $dirs[pathinfo($info['dirname'])['dirname']][pathinfo($info['dirname'])['basename']][] = array('name' => $info['basename'], 'size' => $file[1]);
        }
        else
        {
            $dirs[$info['dirname']][] = array('name' => $info['basename'], 'size' => $file[1]);
        }
    }
    else
    {
        $dirs[] = array('name' => $info['basename'], 'size' => $file[1]);
    }
}

如果我从文件列表数组中删除 dir3 级别,此代码将返回数组正常,但在 dir3 存在的情况下,它给出:

Array
(
    [dir1/dir2] => Array
        (
            [dir3] => Array
                (
                    [0] => Array
                        (
                            [name] => file1.mkv
                            [size] => 44444
                        )

                    [1] => Array
                        (
                            [name] => file2.mkv
                            [size] => 44444
                        )

                )

        )

    [dir1] => Array
        (
            [dir2] => Array
                (
                    [0] => Array
                        (
                            [name] => file1.mkv
                            [size] => 44444
                        )

                    [1] => Array
                        (
                            [name] => file2.txt
                            [size] => 11111
                        )

                )

            [0] => Array
                (
                    [name] => file1.exe
                    [size] => 22222
                )

            [1] => Array
                (
                    [name] => file2.exe
                    [size] => 22222
                )

        )

    [0] => Array
        (
            [name] => file1.rar
            [size] => 3333
        )

)

这个 [dir1/dir2] 是问题所在,我需要它是一棵完美的树,这样我就可以遍历它并将记录插入数据库。

【问题讨论】:

    标签: php mysql arrays json tree


    【解决方案1】:

    由于您事先不知道树的深度,因此您无法使用 if/else 循环来管理它。这是一个需要递归的用例。

    <?php
    function scanpath($path) {
        $myscan = scandir($path);
        $tree=[];
        foreach($myscan as $entry) {
            //echo '<br>'.$entry;
            if($entry==='.' || $entry ==='..') {
                // do nothing
            } else  if(is_dir($path.'/'.$entry)) {
                // this is a folder, I will recurse
                $tree[$entry] = scanpath($path.'/'.$entry);
            } else {
                // this is a file or link. Value is file size
                $tree[$entry] = filesize($path.'/'.$entry);
            }
        }
        return $tree;
    }
    $scanresult=scanpath(__DIR__);
    echo '<pre>';
    print_r($scanresult);
    echo '</pre>';
    

    你看,我在给定路径上调用了一个函数。对于该路径上的每个条目,我

    • 丢弃。和..
    • 如果是文件夹,节点将包含将该函数应用于子路径的结果
    • 在任何其他情况下,节点将包含文件大小

    您需要修改我的代码以满足您的需要。我可以告诉你“是文件还是链接”的情况有不同的格式。

    编辑:由于没有要扫描的真实文件结构,而是您有一个路径数组,这就是我提供的解决方案

    <?php
    $thefiles=[];
    
    $thefiles[] = array('dir1/dir2/dir3/file1.mkv', 44444);
    $thefiles[] = array('dir1/dir2/dir3/file2.mkv', 44444);
    $thefiles[] = array('dir1/dir2/file1.mkv', 44444);
    $thefiles[] = array('dir1/dir2/file2.txt', 11111);
    $thefiles[] = array('dir1/dir4/file5.mkv', 22444);
    $thefiles[] = array('dir1/dir4/file6.txt', 15111);
    $thefiles[] = array('dir1/file1.exe', 22222);
    $thefiles[] = array('dir1/file2.exe', 22222);
    $thefiles[] = array('file1.rar', 3333);
    
    $filearray=[];
    
    function scanpath($patharray,$filesize) {
        $tree=[];
        if(count($patharray)===1) {
            $filename=array_pop($patharray);
            $tree[] = ['name'=>$filename, 'size'=>$filesize];
        } else {
            $pathpart = array_pop($patharray);
            $tree[$pathpart] = scanpath($patharray,$filesize);
        }
        return $tree;
    }
    
    foreach($thefiles as $fileentry) {
        $patharray=array_reverse(explode('/',$fileentry[0]));
        $thisarray = scanpath($patharray,$fileentry[1]);
        $filearray= array_merge_recursive($filearray,$thisarray);
    }
    
    echo '<pre>';
    print_r($filearray);
    echo '</pre>';
    

    我使用斜杠作为分隔符分解每个路径,然后逐个文件夹地在路径上递归,直到到达最后一部分并且递归以文件名和大小结束。

    【讨论】:

    • 我说文件不存在。它只是一个数组,所以你不能做 scandir() 或 is_dir()
    • 我明白了。对于那个很抱歉。我会在几个小时内试一试。
    • 那将不胜感激:)
    • 看来我的工作正常了,请看我编辑的答案。
    • 您好,抱歉回复晚了。我已经想通了。但是感谢您的帮助:)
    【解决方案2】:

    这是我的方式

    $path='E:\conf\transfer';
    $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);
    $tree_array=array();
    foreach($objects as $name => $object){
        if(in_array($object->getFilename(),array('..','.')) || is_dir($object->getPathname()))
        {
            continue;
        }
        $path_info=explode(DIRECTORY_SEPARATOR ,$object->getPathname());
        $file_name=array_pop($path_info);
        $path_info="['".implode("']['",$path_info)."']";
        $code='$tree_array'.$path_info.'[] = '.'\''.$file_name.'\';';
        eval($code);
    }
    
    var_dump($tree_array);

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-06
      • 2013-08-03
      • 2011-05-18
      • 1970-01-01
      • 1970-01-01
      • 2018-08-03
      • 1970-01-01
      相关资源
      最近更新 更多