Большие текстовые файлы -- так ли это страшно на самом деле

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Sergey_next
Новичок
Новичок
 
Сообщения: 37
Зарегистрирован: 23.03.2009 (Пн) 16:21

Большие текстовые файлы -- так ли это страшно на самом деле

Сообщение Sergey_next » 02.04.2009 (Чт) 15:57

Как найти текст в текстовом файле(*.txt), если этот файл большого размера(>1МБ), с помощью функции INSTR.

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Re: Большие текстовые файлы

Сообщение alibek » 02.04.2009 (Чт) 15:59

А какие самостоятельные мысли были?
Lasciate ogni speranza, voi ch'entrate.

Sergey_next
Новичок
Новичок
 
Сообщения: 37
Зарегистрирован: 23.03.2009 (Пн) 16:21

Re: Большие текстовые файлы

Сообщение Sergey_next » 02.04.2009 (Чт) 16:14

Я могу найти слово в файле, если, скажем, в нем не боллее 20 строк, но если больше, то уже не находит.

Dim word As String
Dim a As Integer: a = FreeFile
Open FullPathName For Input As a
Do While Not EOF(a)
Line Input #a, word
If InStr(1, word, find_word, vbTextCompare) Then msgbox "Найдено"
Exit Do
End If
Loop
Close f

gjghjc
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 659
Зарегистрирован: 13.10.2002 (Вс) 8:28
Откуда: БАЛАКЛАВА!!

Re: Большие текстовые файлы

Сообщение gjghjc » 02.04.2009 (Чт) 16:33

Код: Выделить всё
Dim word As String
Dim a As Integer: a = FreeFile
Open FullPathName For Input As a
Do While Not EOF(a)
Line Input #a, word   ' Читаем строку в переменную
If InStr(1, word, find_word, vbTextCompare) Then msgbox "Найдено" ' Если совпадает с критерием поиска то матюкаемся об этом
Exit Do ' А ЭТО ЗДЕСЬ ЗАЧЕМ????
End If  ' типа закрыли IF
Loop 'Продолжили выполенние цикла
Close f
Утро добрым не бывает!

Sergey_next
Новичок
Новичок
 
Сообщения: 37
Зарегистрирован: 23.03.2009 (Пн) 16:21

Re: Большие текстовые файлы

Сообщение Sergey_next » 02.04.2009 (Чт) 16:44

Точнее сказать, поиск проходит только в первых (около 15) строках, а в следующих уже не находит.

gjghjc
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 659
Зарегистрирован: 13.10.2002 (Вс) 8:28
Откуда: БАЛАКЛАВА!!

Re: Большие текстовые файлы

Сообщение gjghjc » 02.04.2009 (Чт) 17:23

Sergey_next писал(а):Точнее сказать, поиск проходит только в первых (около 15) строках, а в следующих уже не находит.

Т.е. если первое совпадение было в первых 15-ти строках то дальше уже ничего не ищется?? Я правильно понял?
Утро добрым не бывает!

SSecurity
Служба безопасности
Аватара пользователя
 
Сообщения: 1283
Зарегистрирован: 19.08.2003 (Вт) 1:11
Откуда: Россия, Мурманск

Re: Большие текстовые файлы

Сообщение SSecurity » 02.04.2009 (Чт) 17:36

я обычно бинарно открываю файл и считываю блоками по 50к потом уже калдую над ним ... очень быстро открывается:)

по коду - открываем А, а закрываем F :)
Программист - это маленький Бог, а все его ошибки - это самостоятельные творения:)
Так задумано:)

Zenitchik
Постоялец
Постоялец
 
Сообщения: 369
Зарегистрирован: 21.12.2006 (Чт) 14:48

Re: Большие текстовые файлы

Сообщение Zenitchik » 02.04.2009 (Чт) 21:14

Код: Выделить всё
If InStr(1, word, find_word, vbTextCompare) Then msgbox "Найдено" ' Ага, ага...
Exit Do
End If  ' типа закрыли IF

Вы бы определились, какой из синтаксисов оператора If используете.
Знание английского языка - затрудняет понимание кода

SSecurity
Служба безопасности
Аватара пользователя
 
Сообщения: 1283
Зарегистрирован: 19.08.2003 (Вт) 1:11
Откуда: Россия, Мурманск

Re: Большие текстовые файлы

Сообщение SSecurity » 02.04.2009 (Чт) 21:39

var 1
Код: Выделить всё
Dim I as long, aaa as String, needtext as string, filename as string

I = 0
needtext = "Вася"
FileName = "Васин_файл.txt"

if DIR(FileName)<>"" then
Open FileName FOR input as #1
do
line input #1, aaa
if instr(1,aaa,needtext,vbTextCompare)<>0 then
  I = I + 1
  debug.print "Строка "; I; ", содержит что надо..."
end if
loop until(eof(1))
close #1
else
  msgbox "в этом файле точно нет ничего"
end if


var 2

Код: Выделить всё
Dim I as long, needtext as string, filename as string
Dim AAA as string * 50000
Dim Buffer as String

needtext = "Вася"
FileName = "Васин_файл.txt"

if DIR(FileName)<>"" then
Open FileName FOR BINARY as #1
For I = 0 to filelen(FileName)/50000
  GET #1, I*50000+1,AAA
  Buffer = Buffer & AAA
Next I
Buffer = Left$(Buffer,filelen(FileName))
close #1

if instr(1,Buffer,needtext,vbTextCompare)=0 then
  msgbox "В этом файле нету твоей строки"
else
  PP = 0
  WHILE instr(PP+1,Buffer,needtext,vbTextCompare)<>0
     PP = instr(PP+1,Buffer,needtext,vbTextCompare)
     debug.print "Байт вхождения: "; PP; ", содержит что надо..."     
  WEND
end if
else
  msgbox "в этом файле точно нет ничего"
end if



UPDATE: проапдейтил строку
Код: Выделить всё
GET #1, A*50000+1,AAA
в
Код: Выделить всё
GET #1, I*50000+1,AAA
просто обшибся непроверяючи
Алибэк: спасибо за поправку
Последний раз редактировалось SSecurity 02.04.2009 (Чт) 22:57, всего редактировалось 2 раз(а).
Программист - это маленький Бог, а все его ошибки - это самостоятельные творения:)
Так задумано:)

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Re: Большие текстовые файлы

Сообщение alibek » 02.04.2009 (Чт) 22:43

Второй вариант кривой. При чтении очередного блока надо сдвигаться назад на длину искомой строки.
Lasciate ogni speranza, voi ch'entrate.

SSecurity
Служба безопасности
Аватара пользователя
 
Сообщения: 1283
Зарегистрирован: 19.08.2003 (Вт) 1:11
Откуда: Россия, Мурманск

Re: Большие текстовые файлы

Сообщение SSecurity » 02.04.2009 (Чт) 22:56

alibek писал(а):Второй вариант кривой. При чтении очередного блока надо сдвигаться назад на длину искомой строки.

Зачем, позволь спросить? .. просто интересно,

На мой взгляд:
ПОИСК АА в ААААА
тут даст: 1,2,3,4
если сдвигать вперед на величину искомого значения даст: 1,3
если сдвигать назад в цикл зайдет:)

П.С.: ошибку при считывании блоков устранил :)))
Программист - это маленький Бог, а все его ошибки - это самостоятельные творения:)
Так задумано:)

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Re: Большие текстовые файлы

Сообщение alibek » 03.04.2009 (Пт) 8:03

Подумай сам.
Представь, что ты ищешь "abcd". И эта строка будет как раз между блоками.
Lasciate ogni speranza, voi ch'entrate.

SSecurity
Служба безопасности
Аватара пользователя
 
Сообщения: 1283
Зарегистрирован: 19.08.2003 (Вт) 1:11
Откуда: Россия, Мурманск

Re: Большие текстовые файлы

Сообщение SSecurity » 03.04.2009 (Пт) 10:06

alibek писал(а):Подумай сам.
Представь, что ты ищешь "abcd". И эта строка будет как раз между блоками.

Может я не так написал? но мы не AAA проверяем а Buffer, который = все блоки вместе :)
Программист - это маленький Бог, а все его ошибки - это самостоятельные творения:)
Так задумано:)

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Re: Большие текстовые файлы

Сообщение alibek » 03.04.2009 (Пт) 10:09

Ну тогда это глупо.
Считывай в буфер разом.
Твоя "оптимизация" будет потреблять памяти вдвое больше и работать на порядок медленнее, чем считывание всего файла за раз.
Lasciate ogni speranza, voi ch'entrate.

awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Re: Большие текстовые файлы

Сообщение awl100Alex » 05.04.2009 (Вс) 23:49

SSecurity
Первый вариант кода неточный - определяет только в какой строке нашли, без получения позиции.
Второй вариант действительно какой-то медленный получился. Поиск в text-файле 1.02 Мб занял целых 55 сек со 100% загрузкой проца! Комп вообще "застыл" на это время. :(
Да ещё вот тут сам замедляешь дополнительно...
Код: Выделить всё
WHILE instr(PP+1,Buffer,needtext,vbTextCompare)<>0
     PP = instr(PP+1,Buffer,needtext,vbTextCompare)

Зачем-то заставляешь машину уже найдя совпадение, во второй строке "отпрыгнуть" назад и снова повторить поиск.
Хотя одно из преимуществ то, что находится всё... несмотря на регистр.
Но я думаю, что лучше всё-таки использовать бинарный поиск, что будет значительно быстрее и точнее (даже в отношении регистра), а так же согласен с alibek - считывать весь файл в буфер, а не фрагментами. Но как это реализовать в строковых, если объявлено Dim Buffer as String ??? При Dim Buffer() as String - InStr генерит ошибку Type. :(

iGrok
Артефакт VBStreets
Артефакт VBStreets
 
Сообщения: 4272
Зарегистрирован: 10.05.2007 (Чт) 16:11
Откуда: Сетевое сознание

Re: Большие текстовые файлы

Сообщение iGrok » 06.04.2009 (Пн) 2:22

awl100Alex писал(а):Но как это реализовать в строковых, если объявлено Dim Buffer as String ??? При Dim Buffer() as String - InStr генерит ошибку Type. :(

Эээ... Зачем Buffer() As String??? :shock:

Код: Выделить всё
Dim hF as Long, sBuffer as String
hF = FreeFile
Open sFileName For Binary as hF
sBuffer = space$(LOF(hF))
Get #hF, , sBuffer
Close #hF
label:
cli
jmp label

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Re: Большие текстовые файлы

Сообщение alibek » 06.04.2009 (Пн) 7:21

А зачем sBuffer as String?
Dim buff() As Byte
ReDim buff(0 To LOF(hF)-1)
Get #hF,,buff
InStr(buff, "string")
Lasciate ogni speranza, voi ch'entrate.

awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Re: Большие текстовые файлы

Сообщение awl100Alex » 06.04.2009 (Пн) 11:06

Воо!! Уже лучше и точней! :)
Код: Выделить всё
Private Sub Command1_Click()
'Поиск слова в больших текстовых файлах...
Dim needtext, sFileName, sBuffer As String, hF, LenStr As Long

needtext = "самолет"
sFileName = App.Path & "\text.txt" '1.02 Мб
LenStr = Len(needtext)

hF = FreeFile
Open sFileName For Binary As hF
sBuffer = Space$(LOF(hF))
Get #hF, , sBuffer
List1.Clear: Label2.Caption = Time
Seek hF, 1
1:  Pos = InStr(Seek(hF), sBuffer, needtext, vbTextCompare)
  If Pos Then
   Seek hF, Pos + LenStr
   List1.AddItem "Искомое слово найдено в позиции - " & Pos
   Label1.Caption = List1.ListCount: Label1.Refresh
   GoTo 1
  End If
  If List1.ListCount = 0 Then MsgBox "Такого слова в файле нет.", vbInformation
Close #hF
Label3.Caption = Time
End Sub

В таком оптимизированном варианте, время поиска (в 1.02 Мб text.txt) составило примерно 25 сек, но всё же вариант alibek, если чисто бинарный поиск по сигнатуре сделать, то время поиска получается 7-10 сек (но правда со строгим учётом регистра - а это может быть и хорошо... еще точней!). :)

awl100Alex
Постоялец
Постоялец
 
Сообщения: 355
Зарегистрирован: 29.01.2008 (Вт) 15:19
Откуда: Украина

Re: Большие текстовые файлы

Сообщение awl100Alex » 06.04.2009 (Пн) 11:18

Да ещё и в документах Word можно тоже поиск слов организовать, если нужно будет. :)


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 29

    TopList  
cron