произвольный доступ к файлу php и сохранение объекта в файл - PullRequest
3 голосов
/ 30 октября 2010

У меня есть CSV-файл с записями, отсортированными по первому полю . Мне удалось создать функцию, которая выполняет бинарный поиск по этому файлу, используя fseek для произвольного доступа через файл.

Однако, это все еще довольно медленный процесс, так как, когда я ищу какую-то позицию в файле, мне действительно нужно смотреть влево, ища \ n символ, чтобы я мог убедиться, что я читаю целую строку (один раз целую строку прочитано, я могу проверить первое значение поля, упомянутое выше).

Вот функция, которая возвращает строку, содержащую символ в позиции x :


function fgetLineContaining( $fh, $x ) {
        if( $x  125145411) // 12514511 is the last pos in my file
            return "";
        // now go as much left as possible, until newline is found
        // or beginning of the file
        while( $x > 0 && $c != "\n" && $c != "\r") {
            fseek($fh, $x);
            $x--; // go left in the file
            $c =  fgetc( $fh );
        }
        $x+=2; // skip newline char
        fseek( $fh, $x );
        return fgets( $fh, 1024 ); // return the line from the beginning until \n
    }

Хотя это работает, как и ожидалось, мне грустно, что мой CSV-файл имеет ~ 1,5 миллиона строк, и этот левый поиск в значительной степени замедляет работу.

Есть ли лучший способ искать строку, содержащую позицию x внутри файла?

Кроме того, было бы намного лучше, если бы объект класса мог быть сохранен в файл без его сериализации, что позволило бы читать файл объект за объектом. Php поддерживает это?

Спасибо

1 Ответ

1 голос
/ 30 октября 2010

Я думаю, вам действительно стоит подумать об использовании SQLite или MySQL снова (как другие предлагали в комментариях). Большинство предложений о предварительном расчете индексов уже реализованы «должным образом» в этих механизмах SQL.

Вы сказали, что скорость не была достаточно хорошей в SQL. Были ли поля проиндексированы правильно? Как вы запрашивали данные? Где вы используете массовые запросы, где вы используете подготовленные заявления? Был ли у процесса SQL достаточно оперативной памяти для хранения его индексов в оперативной памяти?

Одна вещь, которую вы можете попытаться ускорить в соответствии с текущим алгоритмом, - это загрузить файл (~ 100 МБ?) На диск RAM. Независимо от того, что вы выбрали, будь то CVS или SQLite, это БУДЕТ ускорить процесс, особенно если узким местом является время поиска жесткого диска.

Вы могли бы даже прочитать весь файл в массиве PHP (при условии, что на вашем компьютере достаточно оперативной памяти). Это позволит вам выполнять поиск с помощью поиска по индексу ($big_array[$offset]).

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

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