Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.143.9.115] |
|
Страницы: (2) [1] 2 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Добрый день, Уважаемые форумчане.
У меня возник такой вопрос: Строки текстового файла 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 гигабайта, не загружая память и при этом, иметь, хотя бы, среднюю скорость обработки ?. Заранее благодарен за помощь... |
Сообщ.
#2
,
|
|
|
Хэши.
|
Сообщ.
#3
,
|
|
|
Fr0sT не совсем удобно, т.к. сами строки откуда ты будешь брать?
Kirilis2018, у меня дежавю? Все обсасывалось в предыдущих твоих запросах Удалить дубликаты строк - Delphi/RAD XE3+ (сообщение #3767071) Добавлено 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; |
Сообщ.
#4
,
|
|
|
Цитата ^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, Спасибо тебе огромное, твой вариант работает ОТЛИЧНО! |
Сообщ.
#5
,
|
|
|
Первый:
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; Второй: 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; Третий: 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 Извинений, все работает. Просто у меня сам движок заглючил. Только проверил, все работает отлично! |
Сообщ.
#6
,
|
|
|
Цитата ^D^ima @ Fr0sT не совсем удобно, т.к. сами строки откуда ты будешь брать? В смысле? Из файлов читать. Просто хранить в памяти не строки целиком, а короткие хеши. |
Сообщ.
#7
,
|
|
|
Цитата Fr0sT @ Просто хранить в памяти не строки целиком, а короткие хеши. А дальше? Ну нашел ты что, например, не совпадают хеши, затем придется весь файл до нужной строки каждый раз считывать |
Сообщ.
#8
,
|
|
|
Kirilis2018
Кстати, я не совсем верно понял задание из 1 поста. В выходной файл должны попадать только те строки и только из 2 файла, которых нет в первом. В моем коде попадают вообще все уникальные строки. Если нужно придерживаться строго задания в 1 посте, тогда этот код корректнее: 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; |
Сообщ.
#9
,
|
|
|
^D^ima
твой вариант так же будет падать с OutOfMemory, ты ж все строки в память загружаешь. А так, в случае топикстартера возможно будет проще таскать с собой какой нить firebird embeded или Sqlite(вот за него не поручусь, будет ли он коректно работать с такими объемами) тупо влить все данные в две таблицы и результат запроса select File2.Field from File2 left join File1 on File2.Field = File2.Field where File1.Field is null сохранить в файл |
Сообщ.
#10
,
|
|
|
jack128
Там есть нюанс что ты не через loadformfile или stream делаешь, а построчно, это избавляет от такого эффекта |
Сообщ.
#11
,
|
|
|
Цитата ^D^ima @ Кстати, я не совсем верно понял задание из 1 поста. В выходной файл должны попадать только те строки и только из 2 файла, которых нет в первом. В моем коде попадают вообще все уникальные строки. Если нужно придерживаться строго задания в 1 посте, тогда этот код корректнее: Реально, у меня нет слов, просто шикарно работает, этот вариант Вещь . Благодарен тебе за такой подарок. Код работает и легко справляется с поставленными задачами. Большущий тебе RESPECT!!! |
Сообщ.
#12
,
|
|
|
Цитата ^D^ima @ А дальше? Ну нашел ты что, например, не совпадают хеши, затем придется весь файл до нужной строки каждый раз считывать Да, точно. Помню из прошлой темы. Можно хранить смещения вместе с хешами, потом повторно считывать строку. Цитата ^D^ima @ Там есть нюанс что ты не через loadformfile или stream делаешь, а построчно, это избавляет от такого эффекта С чего бы? |
Сообщ.
#13
,
|
|
|
Цитата ^D^ima @ Там есть нюанс что ты не через loadformfile или stream делаешь, а построчно, это избавляет от такого эффекта ровно на 1 гиге возможно, пролучит человек файл в 1,5-2 гига - и снова outOfMemory |
Сообщ.
#14
,
|
|
|
Цитата Fr0sT @ С чего бы? ты же сам спрашивал: Перемешивание строк / Delphi/RAD XE4 (сообщение #3763574) |
Сообщ.
#15
,
|
|
|
Цитата ^D^ima @ Да, спрашивал, но я не об этом. Построчное чтение, конечно, отодвигает фатальное выжирание памяти, но всё равно - лишь отодвигает. Если файлы по 1 Гб, то в widestring это уже больше 2 Гб (по 2 байта на символ + накладные расходы), а там уже и до лимита для х32 программ недалеко |