За последние 24 часа нас посетили 18205 программистов и 1697 роботов. Сейчас ищут 1485 программистов ...

Подсчет строк в большом файле

Тема в разделе "PHP для новичков", создана пользователем Namer, 18 мар 2011.

  1. Namer

    Namer Активный пользователь

    С нами с:
    14 апр 2010
    Сообщения:
    492
    Симпатии:
    0
    Часто возникает необходимость считать количество строк в большом текстовом файле. Строк обычно несколько миллионов. Считаю вот таким простым скриптом:
    PHP:
    1. <?php
    2.  
    3. $ofile ="file.txt";//***
    4.  
    5. $handle = fopen($ofile, "r");
    6. while (!feof($handle))  {
    7.     $bufer = fgets($handle);
    8.     $n=$n+1;
    9. }
    10. echo "n=$n";
    11.  
    12. fclose($handle);
    13. ?>
    Так как в файле строк много, то время работы скрипта иногда переваливает более минуты, ну и грузит прилично комп.
    Хотел узнать, может есть альтернативный более удачный способ подсчета количества строк?
     
  2. Gromo

    Gromo Активный пользователь

    С нами с:
    24 май 2010
    Сообщения:
    2.786
    Симпатии:
    2
    Адрес:
    Ташкент
    Namer
    единственная нормальная альтернатива - хранить в базе.

    можно попробовать сделать

    $file = file('file.txt');
    echo sizeof($file);

    однако в этом случае весь файл будет грузится в память.
     
  3. Apple

    Apple Активный пользователь

    С нами с:
    13 янв 2007
    Сообщения:
    4.984
    Симпатии:
    2
    Namer
    Я давноооооооо писал такую штуку, она даже где-то на форуме есть.
    Суть её в том, что просто-напросто в цикле проходимся до конца файла без буферизации.
    Где-то на форуме 100% лежит.
     
  4. Shumomer

    Shumomer Активный пользователь

    С нами с:
    12 мар 2011
    Сообщения:
    194
    Симпатии:
    1
    Адрес:
    из вашего вображения
    Если сервер юниксовый, то лучше воспользоваться вызовом системной команды wc
     
  5. Namer

    Namer Активный пользователь

    С нами с:
    14 апр 2010
    Сообщения:
    492
    Симпатии:
    0
    Совсем без буферизации?
    Спасибо за мысль!
    Я заменил строчку:
    Код (Text):
    1. $bufer = fgets($handle);
    на:
    Код (Text):
    1. fgets($handle);
    и уже стало процентов 10-20 быстрее, деже с такой упрощенной буферизацией.
    А как еще можно ускорить?

    p.s. У тебя столько сообщений, что поиск не помогает :)
     
  6. Namer

    Namer Активный пользователь

    С нами с:
    14 апр 2010
    Сообщения:
    492
    Симпатии:
    0
    Интересная команда, почитал про нее, спасибо, буду знать. Но пока этим занимаюсь на домашнем компе под виндой, а ему такая команда не известна :)
     
  7. Tony

    Tony Активный пользователь

    С нами с:
    22 мар 2011
    Сообщения:
    13
    Симпатии:
    0
    Адрес:
    Russia
    может быть:
    PHP:
    1.  
    2. <?
    3. $file_array =  file ("file.txt");
    4. $num_str =  count($file_array);
    5. echo($num_str);
    6. ?>
    7.  
     
  8. goshalve

    goshalve Guest

    файл запихнуть в базу,
    добавить поля типо характеристкики,или просто характеристики,при каждом обновлении файла соответственно обновлять базу
     
  9. Namer

    Namer Активный пользователь

    С нами с:
    14 апр 2010
    Сообщения:
    492
    Симпатии:
    0
    Я же говорю, что файлы очень большие, 1- 10ГБ. Такой файл в массив не загонишь, будет ошибка: Fatal error: Allowed memory size

    Нужно без дублирования файла в базу обойтись.
     
  10. Shumomer

    Shumomer Активный пользователь

    С нами с:
    12 мар 2011
    Сообщения:
    194
    Симпатии:
    1
    Адрес:
    из вашего вображения
    Если проект потом поедет на хостинг, то, имхо, стоит поставить coreutils и таки воспользоваться wc
     
  11. Namer

    Namer Активный пользователь

    С нами с:
    14 апр 2010
    Сообщения:
    492
    Симпатии:
    0
    Да, спасибо. Я эту команду запомнил и при переезде на Linux обязательно буду использовать. Но сейчас надо под виндой. Может не только Linux, но и винда знает сколько в файле строк и из нее можно эту инфу выудить?
    Или как альтернатива кокой-то способ быстрого подсчета строк, как намекнул но не показал Apple :)
     
  12. Apple

    Apple Активный пользователь

    С нами с:
    13 янв 2007
    Сообщения:
    4.984
    Симпатии:
    2
    РНР не предназначен для работы с такими большими данными.
    И если работать уж, то работать надо как можно низкоуровнево - на уровне команд или бинарного чтения без всяких плюшек-хуюшек типа функции file или file_get_contents + explode (жесть, да?).

    Можно распарралеливать процессы чтения по смещению, но это если файл действительно структурирован так, что это сделать возможно.
    Пример перехода на указанныю строку в большом файле на форуме я 200% писал, искать мне лень.

    Сделай на С++
    Будет меньше головной боли. Только никаким malloc(filesize), бгггг
     
  13. Namer

    Namer Активный пользователь

    С нами с:
    14 апр 2010
    Сообщения:
    492
    Симпатии:
    0
    А скажи какая функция РНР позволяет прыгнуть на нужную строчку файла? Может сам соображу если не найду пример твоего скрипта.
    Я так понимаю что эта функция должна возвращать False если попытаться перейти на строчку выходящую за пределы файла. Поэтому можно найти число строк методом деления: например
    - переходим на миллионную строчку, если ее нет, то переходим на 1000000/2 строчку;
    - если 500000 сточка есть, то переходим на (1000000+500000)/2 строчку
    - и т.д.
    и так можно быстренько выйти на последнюю строчку.
     
  14. Namer

    Namer Активный пользователь

    С нами с:
    14 апр 2010
    Сообщения:
    492
    Симпатии:
    0
    Вроде есть похожая хорошая функция fseek(), но как я понял она к сожалению прыгает не по строкам, а по байтам файла.
     
  15. Namer

    Namer Активный пользователь

    С нами с:
    14 апр 2010
    Сообщения:
    492
    Симпатии:
    0
  16. goshalve

    goshalve Guest

    Namer
    Фигасе у тебя файл,береш любую программу которая считает количество \n в этом файле на с++ или дельфи.создаешь базу с полями
    1)filename имя файла
    2)Характеристика 1 ....
    3)Одна из характеристик-это количество строк.
    ПРи каждом обновлении файла соответственно обновлять базу,считать сколько \n удаляется
     
  17. Shumomer

    Shumomer Активный пользователь

    С нами с:
    12 мар 2011
    Сообщения:
    194
    Симпатии:
    1
    Адрес:
    из вашего вображения
    Я про винду и говорю. http://gnuwin32.sourceforge.net/packages/coreutils.htm
     
  18. MiksIr

    MiksIr Активный пользователь

    С нами с:
    29 ноя 2006
    Сообщения:
    2.339
    Симпатии:
    44
    PHP:
    1. <?php
    2.  
    3. $ofile ="file.txt";//***
    4.  
    5. $handle = fopen($ofile, "r");
    6. $n = 0;
    7. while (($c = fgetc($handle)) !== FALSE)
    8. {
    9.     if ($c === "\n")
    10.         $n ++;
    11. }
    12. echo "n=$n";
    13.  
    14. fclose($handle);
    15. ?>
     
  19. asik

    asik Активный пользователь

    С нами с:
    12 июл 2007
    Сообщения:
    211
    Симпатии:
    0
    попробуй так:
    PHP:
    1.  
    2. <?php
    3. //......
    4. while (!feof($handle))    {
    5.      $bufer = fread($handle,1048576);
    6.      $n+=substr_count($bufer,"\r");
    7.  }
    8. //.....
    9.  
     
  20. asik

    asik Активный пользователь

    С нами с:
    12 июл 2007
    Сообщения:
    211
    Симпатии:
    0
  21. asik

    asik Активный пользователь

    С нами с:
    12 июл 2007
    Сообщения:
    211
    Симпатии:
    0
    n=9920737 executing 0.27495288848877 sec.
     
  22. asik

    asik Активный пользователь

    С нами с:
    12 июл 2007
    Сообщения:
    211
    Симпатии:
    0
    PHP:
    1. <?php
    2.  
    3. function getmicrotime()
    4. {
    5.     list($usec, $sec) = explode(" ", microtime());
    6.     return ((float)$usec + (float)$sec);
    7. }
    8.  
    9. $time_start = getmicrotime();
    10.  
    11. $ofile ="file.txt";//***
    12. $handle = fopen($ofile, "r");
    13. $n=0;
    14.   while (!feof($handle))    
    15.   {
    16.       $bufer = fread($handle,1048576);
    17.       $n+=substr_count($bufer,"\n");
    18.   }
    19. echo "n=$n";
    20.  
    21. fclose($handle);
    22.  
    23. $time_end = getmicrotime();
    24. $time = $time_end - $time_start;
    25.  
    26. echo "executing $time sec.";
    27. ?>
     
  23. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    а где же самая известная оптимизация всех времен?
    PHP:
    1. $n++;
     
  24. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    Только чтение с диска 10Г-файла займёт несколько минут ;)
     
  25. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    Namer
    файлы очень большие, 1- 10ГБ
    что это такое где надо считать строки в гб файлах. расскажи подробнее