На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
... (продолжение следует) ...

Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.


Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...
Модераторы: jack128, D[u]fa, Shaggy, Rouse_
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Сравнение текстовых файлов \ Варианты
    Добрый день, Уважаемые форумчане.

    У меня возник такой вопрос: Строки текстового файла 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 (Загрузка в память):

    ExpandedWrap disabled
      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 (Чтение построчно):

    ExpandedWrap disabled
      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 гигабайта, не загружая память и при этом, иметь, хотя бы, среднюю скорость обработки ?. Заранее благодарен за помощь...
    Сообщение отредактировано: Kirilis2018 -
      Хэши.
        Fr0sT не совсем удобно, т.к. сами строки откуда ты будешь брать?

        Kirilis2018, у меня дежавю? Все обсасывалось в предыдущих твоих запросах

        Удалить дубликаты строк - Delphi/RAD XE3+ (сообщение #3767071)


        Добавлено
        ExpandedWrap disabled
          Const
          FName:array[1..2] of string = ('c:\1.txt','c:\2.txt');
          MaxFName=2;
          var
            F:TextFile;
            st:string;
            s:TStringList;
            I:Integer;
          begin
            s:=TStringList.Create;
            s.Sorted:=true;
            s.Duplicates:=dupIgnore;
           
            For I:=1 to MaxFName do
              begin
                AssignFile(F,FName[I]);
                reset(f);
                  While not EOF(f) do
                    begin
                      readln(F,st);
                      s.Add(st);
                    end;
                CloseFile(f);
               end;
           
            s.SaveToFile('c:\321.txt');
            s.Free;
           
          end;
          Цитата ^D^ima @
          Const
          FName:array[1..2] of string = ('c:\1.txt','c:\2.txt');
          MaxFName=2;
          var
            F:TextFile;
            st:string;
            s:TStringList;
            I:Integer;
          begin
            s:=TStringList.Create;
            s.Sorted:=true;
            s.Duplicates:=dupIgnore;
           
            For I:=1 to MaxFName do
              begin
                AssignFile(F,FName[I]);
                reset(f);
                  While not EOF(f) do
                    begin
                      readln(F,st);
                      s.Add(st);
                    end;
                CloseFile(f);
               end;
           
            s.SaveToFile('c:\321.txt');
            s.Free;
           
          end;

          D^ima, Спасибо тебе огромное, твой вариант работает ОТЛИЧНО!
            Первый:
            ExpandedWrap disabled
              procedure TForm1.Button1Click(Sender: TObject);
              Const
              FName:array[1..2] of string = ('c:\1.txt','c:\2.txt');
              MaxFName=2;
              var
                F:TextFile;
                st:string;
                s:TStringList;
                I:Integer;
              begin
                s:=TStringList.Create;
                s.Sorted:=true;
                s.Duplicates:=dupIgnore;
               
                For I:=1 to MaxFName do
                  begin
                    AssignFile(F,FName[I]);
                    reset(f);
                      While not EOF(f) do
                        begin
                          readln(F,st);
                          s.Add(st);
                        end;
                    CloseFile(f);
                   end;
               
                s.SaveToFile('c:\321.txt');
                s.Free;
               
              end;


            Второй:
            ExpandedWrap disabled
              procedure TForm1.Button1Click(Sender: TObject);
              Const
              MaxFName=2;
              var
                FName:array[1..2] of string;
                F:TextFile;
                st:string;
                s:TStringList;
                I:Integer;
              begin
                FName[1]:= edit1.text;
                FName[2]:= edit2.text;
               
                s:=TStringList.Create;
                s.Sorted:=true;
                s.Duplicates:=dupIgnore;
               
                For I:=1 to MaxFName do
                  begin
                    AssignFile(F,FName[I]);
                    reset(f);
                      While not EOF(f) do
                        begin
                          readln(F,st);
                          s.Add(st);
                        end;
                    CloseFile(f);
                   end;
               
                s.SaveToFile('Rezultat.txt');
                s.Free;
               
              end;


            Третий:
            ExpandedWrap disabled
              procedure TForm1.Button1Click(Sender: TObject);
              Const
              MaxFName=2;
              var
                F:TextFile;
                st:string;
                s:TStringList;
                I:Integer;
              begin
                s:=TStringList.Create;
                s.Sorted:=true;
                s.Duplicates:=dupIgnore;
               
               
                For I:=1 to MaxFName do
                  begin
                    AssignFile(F,TEdit(FindComponent('Edit' + IntToStr(I) )).Text);
                    reset(f);
                      While not EOF(f) do
                        begin
                          readln(F,st);
                          s.Add(st);
                        end;
                    CloseFile(f);
                   end;
               
                s.SaveToFile('c:\Rezultat.txt');
                s.Free;
               
              end;


            ^D^ima, 10000000000 Извинений, все работает. Просто у меня сам движок заглючил. Только проверил, все работает отлично!
            Сообщение отредактировано: Kirilis2018 -
              Цитата ^D^ima @
              Fr0sT не совсем удобно, т.к. сами строки откуда ты будешь брать?

              В смысле? Из файлов читать. Просто хранить в памяти не строки целиком, а короткие хеши.
                Цитата Fr0sT @
                Просто хранить в памяти не строки целиком, а короткие хеши.

                А дальше? Ну нашел ты что, например, не совпадают хеши, затем придется весь файл до нужной строки каждый раз считывать
                  Kirilis2018
                  Кстати, я не совсем верно понял задание из 1 поста. В выходной файл должны попадать только те строки и только из 2 файла, которых нет в первом. В моем коде попадают вообще все уникальные строки. Если нужно придерживаться строго задания в 1 посте, тогда этот код корректнее:
                  ExpandedWrap disabled
                    procedure TForm1.Button1Click(Sender: TObject);
                    Const
                    MaxFName=2;
                    var
                      F:TextFile;
                      st:string;
                      sl:array[1..MaxFName]of TStringList;
                      I,I2:Integer;
                    begin
                      For I:=1 to MaxFName do
                        begin
                     
                         sl[I]:=TStringList.Create;
                         sl[I].Sorted:=true;//использовать по желанию
                         sl[I].Duplicates:=dupIgnore;//использовать по желанию
                     
                          AssignFile(F,TEdit(FindComponent('Edit' + IntToStr(I) )).Text);
                          reset(f);
                            While not EOF(f) do
                              begin
                                readln(F,st);
                                sl[I].Add(st);
                              end;
                          CloseFile(f);
                     
                         end;
                     
                        AssignFile(F,'c:\Rezultat.txt');
                        rewrite(F);
                     
                        for i:=0 to sl[2].Count-1 do
                        If sl[1].IndexOf(sl[2].Strings[I])=-1 then Writeln(F,sl[2].Strings[I]);
                     
                     
                        CloseFile(f);
                     
                        sl[1].Free;
                        sl[2].Free;
                     
                    end;
                    ^D^ima
                    твой вариант так же будет падать с OutOfMemory, ты ж все строки в память загружаешь.

                    А так, в случае топикстартера возможно будет проще таскать с собой какой нить firebird embeded или Sqlite(вот за него не поручусь, будет ли он коректно работать с такими объемами) тупо влить все данные в две таблицы и результат запроса
                    ExpandedWrap disabled
                      select File2.Field
                      from File2 left join File1 on File2.Field = File2.Field
                      where File1.Field is null

                    сохранить в файл
                      jack128
                      Там есть нюанс что ты не через loadformfile или stream делаешь, а построчно, это избавляет от такого эффекта
                        Цитата ^D^ima @
                        Кстати, я не совсем верно понял задание из 1 поста. В выходной файл должны попадать только те строки и только из 2 файла, которых нет в первом. В моем коде попадают вообще все уникальные строки. Если нужно придерживаться строго задания в 1 посте, тогда этот код корректнее:

                        Реально, у меня нет слов, просто шикарно работает, этот вариант Вещь :good: . Благодарен тебе за такой подарок. Код работает и легко справляется с поставленными задачами. Большущий тебе RESPECT!!!
                          Цитата ^D^ima @
                          А дальше? Ну нашел ты что, например, не совпадают хеши, затем придется весь файл до нужной строки каждый раз считывать

                          Да, точно. Помню из прошлой темы. Можно хранить смещения вместе с хешами, потом повторно считывать строку.
                          Цитата ^D^ima @
                          Там есть нюанс что ты не через loadformfile или stream делаешь, а построчно, это избавляет от такого эффекта

                          С чего бы?
                            Цитата ^D^ima @
                            Там есть нюанс что ты не через loadformfile или stream делаешь, а построчно, это избавляет от такого эффекта

                            ровно на 1 гиге возможно, пролучит человек файл в 1,5-2 гига - и снова outOfMemory
                              Цитата Fr0sT @
                              С чего бы?

                              ты же сам спрашивал:
                              Перемешивание строк / Delphi/RAD XE4 (сообщение #3763574)
                                Цитата ^D^ima @

                                Да, спрашивал, но я не об этом. Построчное чтение, конечно, отодвигает фатальное выжирание памяти, но всё равно - лишь отодвигает. Если файлы по 1 Гб, то в widestring это уже больше 2 Гб (по 2 байта на символ + накладные расходы), а там уже и до лимита для х32 программ недалеко
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0428 ]   [ 17 queries used ]   [ Generated: 16.04.24, 08:27 GMT ]