2009-08-20 10 views
3

Je voudrais stocker 0 à ~ 5000 adresses IP dans un fichier texte, avec un en-tête non apparenté en haut. Quelque chose comme ceci:Recherche de fichier plat efficace en PHP

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

Maintenant, je voudrais savoir si '5.6.7.8' est dans ce fichier texte en utilisant PHP. J'ai seulement chargé un fichier entier et l'ai traité en mémoire, mais je me demandais s'il y avait un moyen plus efficace de chercher un fichier texte en PHP. J'ai seulement besoin d'un vrai/faux si c'est là.

Quelqu'un pourrait-il jeter de la lumière? Ou serais-je coincé avec le chargement dans le fichier entier en premier?

Merci d'avance!

+0

Pourquoi ne pas charger ceci dans une base de données? – Daniel

+0

Pour une installation facile avec un minimum de prérequis. Dans toute autre circonstance, je choisirais un DB :) –

+0

5k n'est pas beaucoup. Si vous aviez affaire à des données beaucoup plus importantes, vous deviez confier le travail à un outil conçu à cet effet. Voir: http://stackoverflow.com/a/40773407/65732 – sepehr

Répondre

5

5000 n'est pas beaucoup d'enregistrements. Vous pourriez facilement faire ceci:

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

et le rechercher manuellement et ce sera rapide.

Si vous en stockiez beaucoup plus, je vous suggérerais de les stocker dans une base de données conçue pour ce genre de choses. Mais pour 5000, je pense que la recherche pleine charge et brute force est bien.

Ne pas optimiser un problème jusqu'à ce que vous ayez un problème. Il ne sert à rien de surcharger inutilement votre solution.

+0

Je suis d'accord que le fait d'avoir beaucoup d'enregistrements est probablement mieux géré par une table de base de données indexée pour la recherche sur la colonne IP. – localshred

+1

Comme vous l'avez dit, a travaillé un régal et très vite! 'N'optimisez pas un problème jusqu'à ce que vous ayez un problème' Conseil judicieux, merci :) –

+0

Vous pouvez également utiliser [file ('filename.txt')] (http://php.net/manual/ function.file.php) – slosd

1

Je ne suis pas sûr si l'outil de ligne de commande de Perl doit charger le fichier entier pour gérer, mais vous pouvez faire quelque chose de semblable à ceci:

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

Une autre option serait de stocker l'adresse IP est dans séparé fichiers sur la base du premier ou du deuxième groupe:

# 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. 

de cette façon, vous auriez pas nécessairement à vous soucier des fichiers étant si grand que vous encourez une pénalité de performance en chargeant le fichier en mémoire.

+0

+1 Pour scinder les fichiers. Cela réduira les coûts. – Gumbo

0

Vous pourriez débourser et grep pour cela.

0

Vous pouvez essayer fgets()

Il lit une ligne de fichiers en ligne. Je ne suis pas sûr à quel point c'est plus efficace. J'imagine que si la PI était vers le haut du fichier, ce serait plus efficace et si la PI était vers le bas, ce serait moins efficace que de simplement lire tout le dossier.

0

Vous pouvez utiliser la commande GREP avec des backticks sur votre serveur Linux. Quelque chose comme:

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

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

Je ne l'ai pas testé personnellement, mais il y a un bout de code dans le manuel PHP qui est écrit pour un grand parsing du fichier:

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); 

Le snippet a été écrit par l'auteur original: hackajar yahoo com

0

essayez-vous de comparer l'IP actuel avec les fichiers texte énumérés IP? les données non liées wouldnt match de toute façon. donc utilisez simplement strpos sur le contenu du fichier complet (file_get_contents). Pourquoi ne pouvez-vous pas charger ceci dans une base de données?

<?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]!"; 
    } 
?> 
Questions connexes