Модераторы: volvo877, Snowy, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Удаление лишних пробелов из большого файла, Помогите оптимизировать алгоритм 
V
    Опции темы
Newo
Дата 16.1.2009, 23:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 24.12.2008

Репутация: нет
Всего: нет



Суть задачи такая:

Есть большой (до 200мб) файл с ключевыми словами, записанными каждое на новой строчке. Ключевые слова из себя могут представлять что угодно: фразы, отдельные слова и т. п.
Надо:
- удалить все пустые строчки из файла
- удалить все начальные и концевые пробелы в строчках
- заменить несколько подряд идущих пробелов одним
Плюс есть еще один нюанс: в данном файле могут символы с кодом 26 (SUB, конец файла), поэтому если считывать из переменной типа textfile, то дальше этого символа считать не удастся. А надо обработать весь файл. Поэтому я считываю из файла типа file of char.

Суть в том, что мой алгоритм файл обрабатывает нежелательно долго.... Например 100мб файл (примерно 5 млн строчек) обрабатывает более пяти минут. Можете дать советы, как оптимизировать алгоритм? Мне ничего путного в голову не приходит....  smile 

PS Не знал, в какой раздел запостить. Решил сюда в результате. Если я ошибся, модеры, перенесите плз тему

Вот код (функция updatestring разбирается с пробелами в строчке, а cleaner уже с самим файлом):

Код

function updatestring (var s: string): string;
  var
    start, finish, i, len: integer;
    ans: string;
    space: boolean;
  begin
    len:= length (s);

    start:= len + 1;

    for i:=1 to len do
      if s[i]<>' ' then
        begin
          start:= i;
          break;
        end;

    if (start=len+1) then
      begin
        updatestring:='';
        exit;
      end;

    finish:= 0;
    for i:= len downto 1 do
      if s[i]<>' ' then
        begin
          finish:= i;
          break;
        end;

    ans:= '';
    space:= false;

    for i:=start to finish do
      begin
        if s[i]<>' ' then
          begin
            ans:= ans + s[i];
            space:= false;
          end
        else
          if not space then
            begin
              ans:= ans + s[i];
              space:= true;
            end;
      end;

    updatestring:= ans;
  end;

procedure cleaner (filename, directory: string);
  var
    now: char;
    infile: file of char;
    outfile: textfile;
    s: string;
  begin
    assignfile (infile, filename);
    assignfile (outfile, directory+'/'+filename);
    reset (infile);
    rewrite (outfile);

    s:= '';

    while not eof (infile) do
      begin
        read (infile, now);

        if ord(now)=10 then
          begin
            s:= updatestring (s);
            if s<>'' then
              begin
                writeln (outfile, s);
              end;
            s:= '';
          end
        else
          if ord(now)>31 then
            s:= s+now;
      end;

    s:= updatestring(s);
    if s<>'' then
      begin
        writeln (outfile, s);
      end;

    closefile (infile);
    closefile (outfile);
  end;


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

Это сообщение отредактировал(а) Newo - 16.1.2009, 23:57
PM MAIL   Вверх
Фантом
Дата 17.1.2009, 02:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: 2
Всего: 49



Сам по себе алгоритм улучшить, пожалуй, трудно. А вот в его реализации есть одно слабое место: побайтное чтение файлов - штука крайне медленная. В Delphi (да и во всех более-менее современных диалектах Паскаля, кажется) есть блоковый ввод-вывод, которым и стоит воспользоваться. Например, так:

Код

procedure cleaner (filename, directory: string);
  const
    buflen=32768; // пусть буфер будет размером в 32768 символов. В принципе, сюда можно 
               // забить любое большое число, лучше - степень двойки, но уже между 256 и 32768
               // разница в скорости невелика. 
  var
    cblock:array[1..buflen] of char; // это и есть буфер
    now: integer; // теперь это будет индекс символа в буферном массиве 
    infile: file; // Файл для блочного чтения должен быть нетипизированным
    countchar:integer; // счетчик для длины буфера
    outfile: textfile;
    s: string;
  begin
    assignfile (infile, filename);
    assignfile (outfile, directory+'/'+filename);
    reset (infile,1); // второй параметр - размер блока чтения, тут это просто один символ
    rewrite (outfile);
    s:= '';
        
    countchar:=buflen; // предполагаем, что длина файла заведомо больше длины буфера
    while countchar=buflen do // если при последнем чтении считали меньше, чем надо, то файл кончился
      begin        
        blockread(infile,cblock,buflen,countchar); // считали блок в cblock, 
                                                   // количество реально считавшегося попало в countchar
        for now:=1 to countchar do    // обработаем столько, сколько реально считалось
          begin
           if ord(cblock[now])=10 then // тут и далее cblock[now] - обрабатываемый символ
            begin
              s:= updatestring (s);
              if s<>'' then
                begin
                  writeln (outfile, s);
                end;
              s:= '';
            end
           else
            if ord(cblock[now])>31 then
              s:= s+cblock[now];
          end;
      end;    
     
    s:= updatestring(s);
    if s<>'' then
      begin
        writeln (outfile, s);
      end;
    closefile (infile);
    closefile (outfile);
  end;


Функцию updatestring я не менял, да и cleaner постарался модифицировать по минимуму. В принципе, там кое-что еще можно доработать, но и так получается неплохо - у меня при тестовом прогоне на 10-мегабайтном файле (какая-то большая картинка в JPEG, попавшаяся под руку) время обработки уменьшилось с 22 секунд до 5 секунд. Попробуйте разные размеры буфера на нужной Вам системе - возможно, удастся выжать результат и получше.


PM   Вверх
Newo
Дата 17.1.2009, 12:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 24.12.2008

Репутация: нет
Всего: нет



Фантом, спасибо большое!)) Буду пробовать smile 
PM MAIL   Вверх
Newo
Дата 17.1.2009, 12:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 24.12.2008

Репутация: нет
Всего: нет



Сейчас полностью разобрался со считыванием по блокам, все теперь просто летает)) Еще раз большое спасибо!))  smile 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi"
THandle
Rrader
volvo877

Запрещается!

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

2. Публиковать ссылки на варез

3. Оффтопить

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, THandle, Rrader, volvo877.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Object Pascal: кроссплатформенные технологии | Следующая тема »


 




[ Время генерации скрипта: 0.0432 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.