Ordnersuche beschleunigen

nchristoph

Erfahrenes Mitglied
Hallo,

ich habe vor, meine Ordnersuche zu beschleunigen.

Selbige habe ich vor in etwa einem Jahr mit der Hilfe von Yaslaw erstellt.

Leider sind es mittlerweile ca. 5000 Dateien die im Höchstfall durchsucht werden müssen was halt dementsprechend lange dauert.

Hier mal der Code:
PHP:
$dira = './Masslisten';
if (isset($_POST['search_term'])) 
{

	$search = $_POST['search_term'].".pdf";
	
	//Alle Dateien in ein 2-Dimensionalen Array schreiben
	$items = getDirContent($dira);
	//Alle Dateien mit einem bestimmten Namen ausfiltern und in $result zurückgeben
	$result = array();
	foreach($items as $item){
		if($item['name'] == $search){
			$result[] = $item; 
   		}    
	}

	//Ausgabe:
	include('./templates/suchealt/suchetopic.tpl');
	foreach($result as $item){
		$teile = explode("/", $item['path']);
		include('./templates/suchealt/sucheerg.tpl');
	}
include('./templates/suchealt/end.tpl');
}

/**
 * Rekursive Funktion um alle Dateien eines Verzeichnises zu katalogisieren
 * @param String    $dir zu durchsuchendes Verzeichniss
 * @return Array<Array<String>> 
 * @example Return-Value: array('name'=>'test.txt', 'path'=>'C:temp/test.txt')
 */
function getDirContent($dir){
    $items = array();
    if (is_dir($dir)) {
        foreach(scandir($dir) as $file){
            $path = createPath($dir, $file);
            if(is_dir($path) && $file!='.' && $file!='..'){
                $items = array_merge($items, getDirContent($path));
            }elseif(is_file($path)){
                $items[] = array('name' => $file, 'path' => $path);
            } 
        }            
    }
    return $items;
}
 
/**
 * Aus meiner Funktionsbibliothek
 *  createPath: http://wiki.yaslaw.info/wikka/PhpCreatePath
 *
 * mpl           by ERB software
 * @author       stefan.erb(at)erb-software.com
 */
 
/**
 * @param   Strings   zusammenzusetzende Elemente
 * @return  String
 * @example
 *      $path = createPath("C:\\temp\\", "test.txt");
 *      $path = createPath("C:", "temp", "test.txt")
 */
function createPath(){
    $parts = func_get_args();
    array_walk($parts, 'removeLastSeparator');
    return str_replace("\\", "/", implode("/", $parts));    
}
 
/**
 * Hilfsfunktion um die nachgestelltenn / und \ von Pfadelementen zu entfernen
 * Wird von createPath() verwendet
 * @param $part
 */
function removeLastSeparator(&$part){
    $part = preg_replace('/[\/\\\]*$/', '', $part);
}
In den Templates ist nur HTML Code.

Gibt es irgendeine Möglichkeit, diese Art der Abfrage zu beschleunigen?

mfg
 
item: Am besten würdest du dir einen Index anlegen den du einmal pro Tag erneuerst (oder wenn eine neue Datei dazu kommt).

item: ggf ist ein array_filter schneller als eine Schleife um den Namen zu vergleichen

item: ev. ist es schneller wenndu auf einen Eindimensionales Array wechselst. $items[$path] => $file

item: Da du die Resultate aus scandir hast, kannst du die Hilfsfunktionen für die Pfaderstellung auch drastisch reduzieren

item: Den Dateinamen schon beim einlesen filtern. zb mit fnmatch()

item: Das gane in eine Klasse setzen. Macht es nicht umbedingt schneller, aber sauberer mit übergreiffenden Variablen

Ev. ist also sowas schneller
PHP:
$dira = dirname(__FILE__).'/project';
$search = 'include.php';

//Alle include.php suchen
var_dump(FileFilter::run($search, $dira));


class FileFilter{
    private $search;
    private $actPath;
    private $found = array();
    private $badItemNames = array('.', '..');
    
    public function __construct($search){
        $this->search = $search;
    }
    
    public static function run($search, $path){
        $instance = new self($search);
        return $instance->search($path);
    }
    
    public function search($path){
        $this->found = array();
        $this->getFiles($path);
        return $this->found;
    }
    
    private function fileNameFilter($fileName){    
        return (basename($fileName) == $this->search) && is_file($fileName);
    }
    
    private function getPath($itemName){
        return "{$this->actPath}/{$itemName}";
    }
    
    private function getFiles($path){
        $this->actPath = $path;
        
        $items = array_diff(scandir($path), $this->badItemNames);
        $itemPaths = array_map(array($this, 'getPath'), $items);
        $this->found = $this->found + array_filter($itemPaths, array($this, 'fileNameFilter'));
        
        foreach(array_filter($itemPaths, 'is_dir') as $subDir){
            $this->getFiles($subDir);
        }    
    }
}

Nachtrag;
Der Dateinamenfilter kann man auch mit glob() umsetzen - ist wahrscheinlich noch schneller
 
Danke für die Hilfe Yaslaw,

Es ist etwas schneller, aber leider nicht der erhoffte Erfolg.

Wie meinst du das mit dem Index anlegen?

Eine Datei wo alle Pfade eingetragen ist und einfach die Datei durchsuchen?
 

Neue Beiträge

Zurück