Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 23.09.2018, 15:39   #1
Taras2018
Пользователь
 
Аватар для Taras2018
 
Регистрация: 13.01.2018
Сообщений: 47
По умолчанию Сравнение текстовых файлов \ Варианты

Добрый день, Уважаемые форумчане.

У меня возник такой вопрос: Строки текстового файла 1.txt необходимо проверить на совпадение - со строками текстового файла 2.txt. И уникальные строки, которых нет в файле 1.txt, записать в файл 3.txt.

К примеру:

Tекст в первом файле - 1.txt
Test1
Test2
Test3
Test4
Test5

Текст во втором файле - 2.txt
Test1
Test2
Test3
Test4
Test5
Stroka1
Stroka2
stroka3

После сравнения, результат в третьем файле - 3.txt
Stroka1
Stroka2
stroka3

Вот мои решения и их недостатки =>

Вариант №1 (Загрузка в память):
Код:
 
var
  i: integer;
  s1, s2: TStrings;
begin
  s1 := TStringList.Create;
  s2 := TStringList.Create;
  Try
    s1.LoadFromFile('1.txt');
    s2.LoadFromFile('2.txt');
    for i := s1.Count - 1 downto 0 do
      if s2.IndexOf(s1[i]) >= 0 Then
        s1.Delete(i);
    s1.SaveToFile('3.txt');
  Finally
    s1.Free;
    s2.Free;
  End;
end;
Проблема в следующем: Если файл размеров 500 мегабайт то вся память забивается и выскакивает ошибка - Out of memory. Ну это само собой понятно поскольку я загружаю и обрабатываю все в памяти.

Вопрос: Может как то можно оптимизировать код в этом варианте, кто что может подсказать ?

Вариант №2 (Чтение построчно):

Код:
var
  f1, f2, f3: textfile;
  s1, s2: string;
  b: boolean;
begin
  assignfile(f1,  '1.txt');
  assignfile(f2,  '2.txt');
  assignfile(f3, '3.txt');
  rewrite(f3);
  reset(f1);
  while not eof(f1) do
  begin
    readln(f1, s1);
    reset(f2);
    b := true;
    while not eof(f2) and b do
    begin
      readln(f2, s2);
      if s2 = s1 then
        b := false;
    end;
    if b then
      writeln(f3, s1);
  end;
  closefile(f1);
  closefile(f2);
  closefile(f3);
end;
Проблема в следующем: Очень и очень медленно работает, ну и тут принцип понятен:
1.Читаем строку из 1.txt файла
2.Открываем 2.txt, проходим по нему ищем совпадение
3.Закрываем 2.txt файл
И так для каждой строки из первого файла. Это куча времени и затрат.

Вопрос, скорее всего утверждение: В этом варианте, само собой понятно что далеко не уедешь.

П.С: Подскажите еще варианты, при использования которых, можно обрабатывать файлы до 1 гигабайта, не загружая память и при этом, иметь, хотя бы, среднюю скорость обработки ?. Заранее благодарен за помощь...

Последний раз редактировалось Taras2018; 23.09.2018 в 15:48.
Taras2018 вне форума Ответить с цитированием
Старый 23.09.2018, 19:50   #2
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,515
По умолчанию

Вар 1. Out of memory
Не делать S1.Delete(j)
иметь (завести) еще один массив
SetLEngth(mm, s1.Count);
в котором отмечать ОТМЕЧАТЬ(запоминать) строки для последующего удаления
потом s2.Clear(Free)
потом удалить помеченые и сохранить
или же (если удаление снова даст outofmemory) ПОСТРОЧНАЯ запись в файл неотмеченных строк.

вар2.
не читать много-много раз один файл(2.txt) а считать его один раз в StringList и искать ТАМ.
программа — запись алгоритма на языке понятном транслятору
evg_m вне форума Ответить с цитированием
Старый 23.09.2018, 19:52   #3
Taras2018
Пользователь
 
Аватар для Taras2018
 
Регистрация: 13.01.2018
Сообщений: 47
По умолчанию

Цитата:
Сообщение от evg_m Посмотреть сообщение
не читать много-много раз один файл(2.txt) а считать его один раз в StringList и искать ТАМ.
Этого варианта, пример кода сможете привести ?
Taras2018 вне форума Ответить с цитированием
Старый 23.09.2018, 19:58   #4
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,515
По умолчанию

комбинация вар1. и вар2

построчное чтение 1.txt (вар2)
поиск прочитанной строки в StringList(вар1)
программа — запись алгоритма на языке понятном транслятору
evg_m вне форума Ответить с цитированием
Старый 24.09.2018, 08:45   #5
Taras2018
Пользователь
 
Аватар для Taras2018
 
Регистрация: 13.01.2018
Сообщений: 47
По умолчанию

Цитата:
Сообщение от evg_m Посмотреть сообщение
комбинация вар1. и вар2

построчное чтение 1.txt (вар2)
поиск прочитанной строки в StringList(вар1)
В меру своего опыта, так я и не разобрался. Ну ничего, буду копать дальше. И на этом спасибо.
Taras2018 вне форума Ответить с цитированием
Старый 24.09.2018, 13:39   #6
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,238
По умолчанию

Цитата:
Сообщение от Taras2018 Посмотреть сообщение
Подскажите еще варианты, при использования которых, можно обрабатывать файлы до 1 гигабайта, не загружая память и при этом, иметь, хотя бы, среднюю скорость обработки ?. Заранее благодарен за помощь...
скажите, какие размеры у файлов 1.txt и 2.txt (в мегабайтах)?
и какое количество строк в файлах?



Цитата:
Сообщение от Taras2018 Посмотреть сообщение
Строки текстового файла 1.txt необходимо проверить на совпадение - со строками текстового файла 2.txt. И уникальные строки, которых нет в файле 1.txt, записать в файл 3.txt.
в тексте и примере Вы пишете, что нужно найти уникальные строчки в 2.txt

а в коде:
Цитата:
Сообщение от Taras2018 Посмотреть сообщение
Код:
s1.LoadFromFile('1.txt');
    s2.LoadFromFile('2.txt');
    for i := s1.Count - 1 downto 0 do
      if s2.IndexOf(s1[i]) >= 0 Then
        s1.Delete(i);
    s1.SaveToFile('3.txt')
;
уникальные строчки ищутся в 1.txt
как нужно то?



Цитата:
Сообщение от evg_m Посмотреть сообщение
комбинация вар1. и вар2
построчное чтение 1.txt (вар2)
поиск прочитанной строки в StringList(вар1)
я бы тоже начал с этого способа. Если, конечно, файл 2.txt легко помещается в память и размеры файла 1.txt позволяют его обрабатывать построчно (скорость обработки достаточная).

выглядит это так:
Код:
var
  f1, f3: textfile;
  s1 : string;
  ts2: TStrings;
begin
  assignfile(f1, '1.txt');
  assignfile(f3, '3.txt');
  rewrite(f3);
  reset(f1);
  ts2 := TStringList.Create;
  s2.LoadFromFile('2.txt');

  while not eof(f1) do
  begin
    readln(f1, s1);
    if ts2.IndexOf(s1) < 0 
    then 
      writeln(f3, s1);
  end;
  ts2.Free;
  closefile(f3);
  closefile(f1);
end;
ну, и возможны варианты.
например, если отсортировать файл 2.txt, то можно воспользоваться индексированным поиском (см. метод Find()), который работает исключительно быстро.

Последний раз редактировалось Serge_Bliznykov; 24.09.2018 в 13:42.
Serge_Bliznykov вне форума Ответить с цитированием
Старый 24.09.2018, 16:24   #7
Taras2018
Пользователь
 
Аватар для Taras2018
 
Регистрация: 13.01.2018
Сообщений: 47
По умолчанию

Цитата:
Сообщение от Serge_Bliznykov Посмотреть сообщение
скажите, какие размеры у файлов 1.txt и 2.txt (в мегабайтах)?
и какое количество строк в файлах?




в тексте и примере Вы пишете, что нужно найти уникальные строчки в 2.txt

а в коде:уникальные строчки ищутся в 1.txt
как нужно то?


я бы тоже начал с этого способа. Если, конечно, файл 2.txt легко помещается в память и размеры файла 1.txt позволяют его обрабатывать построчно (скорость обработки достаточная).

выглядит это так:
Код:
var
  f1, f3: textfile;
  s1 : string;
  ts2: TStrings;
begin
  assignfile(f1, '1.txt');
  assignfile(f3, '3.txt');
  rewrite(f3);
  reset(f1);
  ts2 := TStringList.Create;
  s2.LoadFromFile('2.txt');

  while not eof(f1) do
  begin
    readln(f1, s1);
    if ts2.IndexOf(s1) < 0 
    then 
      writeln(f3, s1);
  end;
  ts2.Free;
  closefile(f3);
  closefile(f1);
end;
ну, и возможны варианты.
например, если отсортировать файл 2.txt, то можно воспользоваться индексированным поиском (см. метод Find()), который работает исключительно быстро.
Добрый день Сергей. Спасибо за то что помогаете:
Нужно - Уникальные строчки ищутся в 1.txt

А как код будет выглядеть методом метод Find() ?

Размеры файлов по 500 мегабайт. Но к сожалению файл в память не помещается и все равно выскакивает ошибка нехватки памяти.

Последний раз редактировалось Taras2018; 24.09.2018 в 16:34.
Taras2018 вне форума Ответить с цитированием
Старый 24.09.2018, 16:40   #8
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,238
По умолчанию

Цитата:
Сообщение от Taras2018 Посмотреть сообщение
А как код будет выглядеть методом метод Find() ?
да так же.
только добавится сортировка и вместо indexOf() будет вызов метода Find():
Код:
var
  f1, f3: textfile;
  s1 : string;
  ts2: TStrings;
begin
  assignfile(f1, '1.txt');
  assignfile(f3, '3.txt');
  rewrite(f3);
  reset(f1);
  ts2 := TStringList.Create;
  s2.LoadFromFile('2.txt');

  s2.Sort; {внимание! Это длительная операция!}

  while not eof(f1) do
  begin
    readln(f1, s1);
    if ts2.Find(s1) < 0 
    then 
      writeln(f3, s1);
  end;
  ts2.Free;
  closefile(f3);
  closefile(f1);
end;
Serge_Bliznykov вне форума Ответить с цитированием
Старый 24.09.2018, 17:01   #9
Taras2018
Пользователь
 
Аватар для Taras2018
 
Регистрация: 13.01.2018
Сообщений: 47
По умолчанию

Цитата:
Сообщение от Serge_Bliznykov Посмотреть сообщение
да так же.
только добавится сортировка и вместо indexOf() будет вызов метода Find():
Код:
var
  f1, f3: textfile;
  s1 : string;
  ts2: TStrings;
begin
  assignfile(f1, '1.txt');
  assignfile(f3, '3.txt');
  rewrite(f3);
  reset(f1);
  ts2 := TStringList.Create;
  s2.LoadFromFile('2.txt');

  s2.Sort; {внимание! Это длительная операция!}

  while not eof(f1) do
  begin
    readln(f1, s1);
    if ts2.Find(s1) < 0 
    then 
      writeln(f3, s1);
  end;
  ts2.Free;
  closefile(f3);
  closefile(f1);
end;
А в этом коде если использовать то выдает вот такие ошибки, прикрепил картинку.
Изображения
Тип файла: png KKKKKKKK.png (40.4 Кб, 123 просмотров)
Taras2018 вне форума Ответить с цитированием
Старый 24.09.2018, 17:07   #10
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,238
По умолчанию

я опечатался.
там, разумеется, ts2 должно быть:
Код:
  ts2 := TStringList.Create;
  ts2.LoadFromFile('2.txt');

  ts2.Sort; {внимание! Это длительная операция!}
только насчёт сортировки обратите внимание, пожалуйста.
На большом файле, боюсь, что не дождётесь результатов.
Serge_Bliznykov вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
TStringlist - сравнение текстовых файлов с ip и mac Алиби Общие вопросы Delphi 3 27.12.2016 17:35
Сравнение текстовых файлов demon-sheff Общие вопросы Delphi 3 20.05.2013 09:13
Сравнение строк двух текстовых файлов Alina111 Общие вопросы C/C++ 4 10.01.2013 10:03
Самое быстрое сравнение текстовых файлов blblbl-org Общие вопросы Delphi 17 26.04.2012 15:19
Сравнение текстовых файлов BR17UY Общие вопросы Delphi 15 07.05.2007 20:18