Эффективный поиск плоских файлов в PHP - PullRequest
3 голосов
/ 20 августа 2009

Я хотел бы хранить от 0 до ~ 5000 IP-адресов в текстовом файле с несвязанным заголовком вверху. Примерно так:

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

Теперь я хотел бы узнать, находится ли «5.6.7.8» в этом текстовом файле с использованием PHP. Я только когда-либо загружал весь файл и обрабатывал его в памяти, но мне было интересно, есть ли более эффективный способ поиска текстового файла в PHP. Мне нужно только истинное / ложное, если оно есть.

Может ли кто-нибудь пролить свет? Или я застрял бы с загрузкой всего файла первым?

Заранее спасибо!

Ответы [ 7 ]

5 голосов
/ 20 августа 2009

5000 не много записей. Вы можете легко сделать это:

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

и ищите его вручную, и это будет быстро.

Если бы вы хранили намного больше, я бы предложил сохранить их в базе данных, которая предназначена для такого рода вещей. Но за 5000 я думаю, что поиск с полной нагрузкой и перебором - это нормально.

Не оптимизируйте проблему, пока у вас не возникнет проблема. Нет смысла чрезмерно усложнять ваше решение.

1 голос
/ 20 августа 2009

Я не уверен, нужно ли инструменту командной строки perl загружать весь файл для его обработки, но вы могли бы сделать что-то похожее на это:

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

Другой вариант - хранить IP-адреса в отдельных файлах на основе первой или второй группы:

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

Таким образом, вам не обязательно беспокоиться о том, что файлы настолько велики, что вы теряете производительность, загружая весь файл в память.

0 голосов
/ 08 октября 2010

Вы пытаетесь сравнить текущий IP с текстовыми файлами, перечисленными IP? несвязанные данные не будут совпадать в любом случае. поэтому просто используйте strpos для полного содержимого файла (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]!";
    }
?>
0 голосов
/ 26 августа 2009

Я не проверял это лично, но в руководстве по PHP есть фрагмент кода, написанный для анализа больших файлов:

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

Фрагмент был написан оригинальным автором: hackajar yahoo com

0 голосов
/ 20 августа 2009

Вы можете использовать команду GREP с обратными галочками на вашем сервере Linux. Что-то вроде:

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

$grepCmd   = `grep $searchFor $file`;
echo $grepCmd;
0 голосов
/ 20 августа 2009

Вы можете попробовать fgets ()

Он читает файл построчно. Я не уверен, насколько это более эффективно, хотя. Я предполагаю, что если бы IP был в верхней части файла, он был бы более эффективным, а если бы IP был в нижней части, он был бы менее эффективным, чем просто чтение всего файла.

0 голосов
/ 20 августа 2009

Вы могли бы раскошелиться и grep для этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...