• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

    На последнюю неделю приходится экзамен, где нужно будет показать свои навыки, взломав ряд уязвимых учебных сайтов, и добыть флаги. Успешно сдавшие экзамен получат сертификат.

    Запись на курс до 25 апреля. Получить промодоступ ...

Сравнить два текстовых файла

  • Автор темы Guest
  • Дата начала
Статус
Закрыто для дальнейших ответов.
G

Guest

Есть два файла.
В одном 172353 текстовых строк,
Во втором 13433 строки.

Нужно выделить из строки первого файла бранд и номер и определить сколько номеров (по брандам) попало во второй файл, а сколько не попало.

Я написала такую процедурку. Она работает, но медленно.
1 запись из первого файла сравнивается со всеми записями из второго за секунду примерно...
Есть ли возможность обработать эти данные быстрее?

Код:
Sub Click(Source As Button)
Dim text As String
Dim fileAll As Integer, fileSort As Integer
Dim PN_All As String, PN_Sort As String
Dim brand As String, rec As String
Dim PNcount As Double
Dim brandList List As Double
Dim num As Integer

fileAll% = Freefile()
Open "c:\GB_PRICE.CH2" For Input As fileAll%		'Список всех брандов и номеров
fileSort% = Freefile()
Open "c:\GB_ALL.NEW" For Input As fileSort%		'Список номеров прошедших фильтрацию
fileSortRez% = Freefile()
Open "c:\sortrez.txt" For Append As fileSortRez%	'Список брандов и кол-во номеров прошедших фильтрацию
fileNoSortRez% = Freefile()
Open "c:\nosortrez.txt" For Append As fileNoSortRez%	'Списко брандов и кол-во номеров непрошедших фильтрацию

num = 1
PNcount = 0		'Счетчик прошедших фильтрацию
PNNocount = 0		'Счетчик непрошедших фильтрацию
Do While Not Eof(fileAll%)
'Получаем из файла бранд и номер текущий
Line Input #fileAll%, text$ 
brand = Left$(Mid$(text$, 178, 183),5)
PN_All = Left$(text$, 7)

'Если бранд новый, то записываем полученные значения в файл и обнуляем счетчики
If (brandOld <> brand) Or (brandOld = "") Then	
rec = brandold & " " & Cstr(PNcount) 
if brandOld <> "" then Write #fileSortRez%, rec
rec = brandold & " " & Cstr(PNNocount) 
If PNNocount <> 0 Then Write #fileNoSortRez%, rec

PNNocount = 0
PNcount = 0
PNoldcount = 0
End If

'Второй файл перематываем в начало
Seek fileSort%, 1
'Пока не конец файла сравниваем номера из него с запомненным номером
Do While Not Eof(fileSort%)
Line Input #fileSort%, text$ 
PN_Sort = Left$(text$, 7)
'Если находим номер в файле отфильтрованных, то увеличиваем счетчик прошедших фильтрацию
If PN_All = PN_Sort Then 
PNcount = PNcount+1
End If
Loop

'Если номер не найден, то увеличиваем счетчик непрошедших фильтрацию
If PNcount = PNoldcount Then 
PNNocount = PNNocount + 1
End If

'Запоминаем значение счетчика прошедших фильтрацию и название текущего бренда
PNoldcount = PNcount
brandOld = brand

'Выводим подсказку о номере строки которую сравнили
num = num +1
Print Cstr(num)
Loop

'Закрываем все файлы
Close fileAll%
Close fileSort%
Close fileSortRez%
Close fileNoSortRez%	
End Sub
 
Y

Yakov

Считайте второй файл в List, используйте функцию IsElement().
 
T

turumbay

В декларации объявлен список. И это правильно. Тока он не используется...

1. Пройтись один раз по втором файлу( который короче ) -
Do While Not Eof(fileSort%)
Line Input #fileSort%, text$
PN_Sort = Left$(text$, 7)
on error resume next ' в общем-то - необязательно, но все же...
IDCountList( PN_Sort ) = IDCountList( PN_Sort ) + 1
on error goto errhandle
Loop
Поимели список

2. Пройтись по первому файлу:
Do While Not Eof(fileAll%)
'Получаем из файла бранд и номер текущий
Line Input #fileAll%, text$
brand = Left$(Mid$(text$, 178, 183),5)
PN_All = Left$(text$, 7)

if iselement( IDCountList ( PN_All ) ) then
brandFoundList( brand ) = brandFoundList( brand ) + IDCountList ( PN_All )
else
brandNotFoundList( brand ) = brandNotFoundList( brand ) + 1
end if
Loop

3. Имеем 2 списока.
Первый: хэштаблица бранд-число вхождений во второй файл
Второй: хэштаблица бранд - число номеров, не найденных во втором файле
forall brand in brandFoundList
' пишем в файл прошедших
end forall

forall brand in brandNotFoundList
' пишем в один файл непрошедших
end forall


З.Ы. Т.к. первый файл похоже сортированный - можно не собирать списки а сразу писать в файл при смене текущего бранда. Экономим память.
 
G

Guest

Так примерно и сделала.
Файлы не сортированные к сожалению.

Спасибо!!!!! Работает 5 мин.
 
T

turumbay

интересно, а если через API виндовое сделать - быстрее будет? как-то долговато 5 минут...
А это смотря как сделать. Использование апи ни коим образом не вылечит проблему симлинка /dev/hands на /dev/ass. :)

5 минут - многовато, при условии, что проход по второму файлу в первоначальной версии занял 1 секунду.
Если есть желание оптимизировать - то сначала ищем узкое место:
для начала отделяем дисковые операции от операций с памятью - убеждаемся, что не уткнулись в производительность ФС. Если таки файловая система - то забиваем, ибо бессильны.
если проблемы не с чтением/записью - то возможно(!) тормозят строковые операции.
В общем, не зная деталей( не видя кода, который работает 5 минут ), любые выводы о путях оптимизации безосновательны.
 
G

Guest

Оно меньше чем за 5 минут работает. Это я приблизительно сказала. :)
А так по ощущениям за 2 или полторы... не засекала.
 
K

Klido

Если есть желание оптимизировать - то сначала ищем узкое место:

тема грузануть в память файлы и там работать... из-под лотусины напрямую это не сделать...
считывание 175К строк (это 175КХ100примерно в строке=аж 17Мб) 2 сек, на серваке с норм винтами 0.5 сек
про скорость операций в оперативке мы не говорим :)
вся задача СЧИТАТЬ и СРАВНИТЬ... а у нас такой большой код...
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 941
609
BIT
215
поиск в неупорядоченных данных не производительно делать прямым перебором... (есть методы ускоренного поиска)
можно предварительно создать индекс строк 2-го файла (как минимум)

использовать NotesStream - идеологически более правильно :)
 
Статус
Закрыто для дальнейших ответов.
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!