2009-08-20 8 views
3

Ich möchte 0 bis ~ 5000 IP-Adressen in einer einfachen Textdatei speichern, mit einem nicht verwandten Header an der Spitze. Etwas wie dieses:Effiziente Flatfile-Suche in PHP

Unrelated data 
Unrelated data 
----SEPARATOR---- 
1.2.3.4 
5.6.7.8 
9.1.2.3 

Jetzt würde ich gerne finden, wenn '5.6.7.8' ist in dieser Textdatei mit PHP. Ich habe immer nur eine ganze Datei geladen und im Speicher verarbeitet, aber ich habe mich gefragt, ob es eine effizientere Möglichkeit gibt, eine Textdatei in PHP zu durchsuchen. Ich brauche nur ein Wahr/Falsch, wenn es da ist.

Könnte jemand Licht abgeben? Oder würde ich zuerst die ganze Datei laden?

Vielen Dank im Voraus!

+0

Warum können Sie das nicht in eine Datenbank laden? – Daniel

+0

Für einfache Installation mit minimalen Voraussetzungen. Unter anderen Umständen würde ich eine DB wählen :) –

+0

5k ist nicht viel. Wenn Sie mit sehr viel größeren Daten zu tun hatten, mussten Sie den Auftrag an ein Werkzeug übergeben, das für diesen Zweck entwickelt wurde. Siehe: http://stackoverflow.com/a/40773407/65732 – sepehr

Antwort

5

5000 ist nicht viele Datensätze. Man könnte dies leicht tun:

$addresses = explode("\n", file_get_contents('filename.txt')); 

und suchen Sie es manuell und es wird schnell sein.

Wenn Sie viel mehr speichern würden, würde ich vorschlagen, sie in einer Datenbank zu speichern, die für diese Art von Sache ausgelegt ist. Aber für 5000 halte ich die Volllast plus Brute-Force-Suche für gut.

Optimieren Sie ein Problem erst, wenn Sie ein Problem haben. Es hat keinen Sinn, Ihre Lösung unnötig zu komplizieren.

+0

Ich stimme zu, dass viele Datensätze wahrscheinlich besser von einer Datenbanktabelle verarbeitet werden, die für die Suche in der IP-Spalte indiziert ist. – localshred

+1

Wie du schon sagtest, es hat sehr gut funktioniert und sehr schnell! "Optimiere ein Problem nicht, bis du ein Problem hast" Klare Ratschläge, danke :) –

+0

Als Alternative kannst du auch [file ('filename.txt')] verwenden (http://php.net/manual/) funktion.datei.php) – slosd

1

Ich bin mir nicht sicher, ob Kommandozeilen-Tool Perl muss die gesamte Datei laden, sie zu handhaben, aber man könnte etwas ähnliches tun:

<?php 
... 
$result = system("perl -p -i -e '5\.6\.7\.8' yourfile.txt"); 
if ($result) 
    .... 
else 
    .... 
... 
?> 

Eine weitere Möglichkeit, die IP-Adressen in separaten zu speichern wäre basierten Dateien auf der ersten oder zweiten Gruppe:

# 1.2.txt 
1.2.3.4 
1.2.3.5 
1.2.3.6 
... 

# 5.6.txt 
5.6.7.8 
5.6.7.9 
5.6.7.10 
... 

... etc. 

auf diese Weise würden Sie nicht unbedingt Sorgen machen müssen über die Dateien so groß ist, um eine Leistungseinbuße Sie entstehen durch die gesamte Datei in den Speicher geladen werden.

+0

+1 Zum Aufteilen der Dateien. Das wird die Kosten senken. – Gumbo

0

Sie könnten Shell und Grep dafür.

0

könnten Sie fgets() versuchen

Es liest eine Datei Zeile für Zeile. Ich bin mir nicht sicher, wie viel effizienter das ist. Ich vermute, dass, wenn die IP in Richtung der Spitze der Datei wäre, es effizienter wäre und wenn die IP nach unten gehen würde, wäre es weniger effizient als nur das Einlesen der gesamten Datei.

0

Sie könnten den GREP-Befehl mit Backticks auf Ihrem Linux-Server verwenden. Etwas wie:

$searchFor = '5.6.7.8'; 
$file  = '/path/to/file.txt'; 

$grepCmd = `grep $searchFor $file`; 
echo $grepCmd; 
0

Ich habe dies persönlich nicht getestet, aber es ist ein Code-Snippet in dem PHP-Handbuch, das für große Datei-Parsing geschrieben:

http://www.php.net/manual/en/function.fgets.php#59393

//File to be opened 
$file = "huge.file"; 
//Open file (DON'T USE a+ pointer will be wrong!) 
$fp = fopen($file, 'r'); 
//Read 16meg chunks 
$read = 16777216; 
//\n Marker 
$part = 0; 

while(!feof($fp)) { 
    $rbuf = fread($fp, $read); 
    for($i=$read;$i > 0 || $n == chr(10);$i--) { 
     $n=substr($rbuf, $i, 1); 
     if($n == chr(10))break; 
     //If we are at the end of the file, just grab the rest and stop loop 
     elseif(feof($fp)) { 
      $i = $read; 
      $buf = substr($rbuf, 0, $i+1); 
      break; 
     } 
    } 
    //This is the buffer we want to do stuff with, maybe thow to a function? 
    $buf = substr($rbuf, 0, $i+1); 
    //Point marker back to last \n point 
    $part = ftell($fp)-($read-($i+1)); 
    fseek($fp, $part); 
} 
fclose($fp); 

Der Snippet wurde vom ursprünglichen Autor geschrieben: hackajar yahoo com

0

versuchen Sie, die aktuelle IP mit den Textdateien gelisteten IPs zu vergleichen? die nicht verwandten Daten würde sowieso nicht übereinstimmen. also benutze einfach strpos auf dem gesamten Dateiinhalt (file_get_contents).

<?php 
    $file = file_get_contents('data.txt'); 
    $pos = strpos($file, $_SERVER['REMOTE_ADDR']); 
    if($pos === false) { 
     echo "no match for $_SERVER[REMOTE_ADDR]"; 
    } 
    else { 
     echo "match for $_SERVER[REMOTE_ADDR]!"; 
    } 
?>