помогите с поиском дескриптора в файле

Программирование на Visual Basic for Applications
Sergeos
Начинающий
Начинающий
 
Сообщения: 8
Зарегистрирован: 17.01.2005 (Пн) 2:04

помогите с поиском дескриптора в файле

Сообщение Sergeos » 17.01.2005 (Пн) 4:30

Есть небольшой вопрос к вам, помогите решить. Есть необходимость в поиске конкретного значения в файле через excell. Тоесть, мне надо найти в файле дескриптор, к примеру, data. Он находиться, допустим, по смещению 35. В excele отображается конкретный офсет и поиск продолжается. Но! Весь процесс занимает очень долгое время, хотя сам файл размером мега на 2. Поэтому вопросы:
1. Я пользуюсь крнструкцией типа: arrDch = Array(100, 97, 116, 97)
eoFile = FileLen("c:\temp\2.nnn")
Open "c:\temp\2.nnn" For Binary As FreeFile ' Open file.
While Not EOF(1)
Get #1, , ch
If Not blnDataFound Then
If arrDch(K) = ch Then
K = K + 1
Else
K = 0
End If
If K > UBound(arrDch) Then blnDataFound = True

End If
Wend
Close #1 ' Close fileEnd Sub

есть ли еще варианты?
2. Я слышал, что можно загрузить весь файл в память расположив его на винте, и производить доступ к памяти. Но, как это реализуется?

3. Как добится той скорости, подобной, как WinHEX ищет значения в файле?

Помогите, если чем можете.
Спасибо.

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 17.01.2005 (Пн) 4:39

Эээээ... Ещё один последователь файлогружения :)
Во-первых, результат функции freefile нужно запоминать в переменную. Иначе какой смысл её использовать, если потом обращение идёт к номеру 1?
Во-вторых, что за странный способ искать совпадения? Дескриптор какого размера, в байтах, и какое у него значение?
И где объявления переменных - при чтении из файла это ой как важно?
И ещё сюда можешь глянуть :)
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Sergeos
Начинающий
Начинающий
 
Сообщения: 8
Зарегистрирован: 17.01.2005 (Пн) 2:04

Сообщение Sergeos » 17.01.2005 (Пн) 5:24

[quote="GSerg"]
Во-вторых, что за странный способ искать совпадения? Дескриптор какого размера, в байтах, и какое у него значение?
И где объявления переменных - при чтении из файла это ой как важно?

Тут я дал вкратце кусок кода, переменные, конечно же есть.
В том то и дело, что дескриптор может быть разной длины, но в основном 3 байта. (от 2 до 5байт, вообще). Можно считывать не побайтно, а по интержно. Результат тот же. Скорость низкая :(

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 17.01.2005 (Пн) 6:24

А может, заюзать файлмаппинги? (это я про "загрузить весь файл в память расположив его на винте, и производить доступ к памяти")
Изображение

Vitaly1
Брехман
Брехман
 
Сообщения: 1578
Зарегистрирован: 30.12.2002 (Пн) 16:35
Откуда: Russia, Mosсow

Сообщение Vitaly1 » 18.01.2005 (Вт) 19:10

Может быть, использовать файл произвольного доступа, и весь файл в закачать в строку, а затем ее обрабатывать?

Вот еще, можешь попробовать: типизируй K и сделай изменения в коде, для ускорения выполнения:

dim k as long, n as long
eoFile = FileLen("c:\temp\2.nnn")
Open "c:\temp\2.nnn" For Binary As FreeFile ' Open file.
n=UBound(arrDch)
k=0
blnDataFound = False
do While Not EOF(1)
Get #1, , ch
If k<=n Then
If arrDch(K) = ch Then
K = K + 1
end if
Else
blnDataFound = True
exit do
End If
loop
Close #1

так будет быстрее, по ряду причин.

Vitaly1
Брехман
Брехман
 
Сообщения: 1578
Зарегистрирован: 30.12.2002 (Пн) 16:35
Откуда: Russia, Mosсow

Сообщение Vitaly1 » 18.01.2005 (Вт) 19:57

А так,наверно, еще быстрее будет:

dim k as long, n as long, arrDch as string, ch as string *1
eoFile = FileLen("c:\temp\2.nnn")
Open "c:\temp\2.nnn" For Binary As FreeFile ' Open file.
arrDch = asc(12) + asc(124)+ asc(56) ' и т.д. какие цифры надо

blnDataFound = False
do While Not EOF(1) AND arrDch <>""
Get #1, , ch ' или надо применить Input, если не пойдет ДЛЯ СЧИТЫВ.
If Mid(arrDch,1,1) = ch Then
arrDch =Mid(arrDch,2)
End If
loop
Close #1

IF arrDch ="" THEN
blnDataFound = True
END IF



А что дескриптор разбросан по всей длине файла, или это байты идущие подрят?

gacol
Начинающий
Начинающий
 
Сообщения: 14
Зарегистрирован: 02.11.2004 (Вт) 13:13
Откуда: Нов. Уренгой

Сообщение gacol » 21.01.2005 (Пт) 7:43

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

Set fs = CreateObject("Scripting.FileSystemObject")
Set A = fs.OpenTextFile(flin$, 1, -2)
c$ = A.Read(1000000) '----- чтение 1 Мб
mesto = InStr(c$, <искомая строка>)

Sergeos
Начинающий
Начинающий
 
Сообщения: 8
Зарегистрирован: 17.01.2005 (Пн) 2:04

Сообщение Sergeos » 22.01.2005 (Сб) 6:11

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

Sergeos
Начинающий
Начинающий
 
Сообщения: 8
Зарегистрирован: 17.01.2005 (Пн) 2:04

Сообщение Sergeos » 22.01.2005 (Сб) 6:17

и еще: как правильнее сделать счетчик найденных значений, или как узнать где конкретно находиться маркер поиска, на каком смещении, ведь знает же он когда конец файла. я думаю, что так:

for i=1 to EOF
Get #1, , ch
If K=true then MsgBox = i
....
....

Next

Sergeos
Начинающий
Начинающий
 
Сообщения: 8
Зарегистрирован: 17.01.2005 (Пн) 2:04

Сообщение Sergeos » 22.01.2005 (Сб) 6:26

Vitaly1 писал(а):Может быть, использовать файл произвольного доступа, и весь файл в закачать в строку, а затем ее обрабатывать?

Вот еще, можешь попробовать: типизируй K и сделай изменения в коде, для ускорения выполнения:

dim k as long, n as long
eoFile = FileLen("c:\temp\2.nnn")
Open "c:\temp\2.nnn" For Binary As FreeFile ' Open file.
n=UBound(arrDch)
k=0
blnDataFound = False
do While Not EOF(1)
Get #1, , ch
If k<=n Then
If arrDch(K) = ch Then
K = K + 1
end if
Else
blnDataFound = True
exit do
End If
loop
Close #1

так будет быстрее, по ряду причин.


кстати, смотри:
в этом коде есть небольшой баг, а именно:
файл считывается, находиться нужный байт, например 65 (A)
К уже присваивается 1
следующий байт FF, нам он не годится, а К все равно единица
потом идет 64
значит К = 2
а это уже неправильно, т.к. мы ищем 65, 100, 111,..., а находит он 65,255, 100, 111...!
Надо как-то и К сбрасывать, понимаешь?

Vitaly1
Брехман
Брехман
 
Сообщения: 1578
Зарегистрирован: 30.12.2002 (Пн) 16:35
Откуда: Russia, Mosсow

Сообщение Vitaly1 » 25.01.2005 (Вт) 14:45

Это другое дело, там оказывается нужно последовательность символов искать! Так исходник ты мне дал не правильный!



Код: Выделить всё
dim k as long, n as long
eoFile = FileLen("c:\temp\2.nnn")
Open "c:\temp\2.nnn" For Binary As FreeFile ' Open file.
n=UBound(arrDch)
k=0
blnDataFound = False
do While Not EOF(1)
Get #1, , ch
NextCh:
'ищим 1 символ
If arrDch(0) = ch Then
K = 0
Do 
Get #1, , ch
k=k+1
loop untile k = n or  arrDch(K) <>ch or EOF(1) = true
 
if arrDch(K) =ch and k=n then
blnDataFound = True
exit do
if EOF(1) = true then
exit do
else
goto NextCh
end if

End If
loop
Close #1


как правильнее сделать счетчик найденных значений, или как узнать где конкретно находиться маркер поиска, на каком смещении, ведь знает же он когда конец файла.

так что надо считать, найденные комбинации символов или определять их место положение, или просто найти комбинацию символов?

Sergeos
Начинающий
Начинающий
 
Сообщения: 8
Зарегистрирован: 17.01.2005 (Пн) 2:04

Сообщение Sergeos » 26.01.2005 (Ср) 22:55

незнаю, правильно ли изложу свою мысль, но мне надо, чтобы когда конкретное значение нашлось, то, допустим, в листбокс добавлялся адрес смещения в файле, например, если значение найдено на смещении 8, значит добавляется 8, дальше это же значение в файле находится 320, добавляется в листбокс 320...и т. д. до конца файла.
Спасибо за код!

Sergeos
Начинающий
Начинающий
 
Сообщения: 8
Зарегистрирован: 17.01.2005 (Пн) 2:04

Сообщение Sergeos » 27.01.2005 (Чт) 1:37

теперь я использую такой код:
------------------
Sub superFinder()
Dim arrDch, K As Byte
Dim ch As Byte
Dim dataReadBool As Boolean

arrDch = Array(65, 100, 111, 98) 'Ищем Adob

Open "c:\shape.bin" For Binary As FreeFile
dataReadBool = False
K = Empty

While dataReadBool <> True
Get #1, , ch
If arrDch(K) = ch Then K = K + 1 Else K = 0
If K > UBound(arrDch) Then dataReadBool = True
Wend

Close #1
End Sub
-------------------------
вроде ищет нормально, ан нет!
вот, например, начало файла, в котором он ничего(код) не найдет:

41 20 6F 62 20 41 64 64 6F 62 65 20 41 41 64 6F
62 65 20 00 00 00 00 00 00 00 00 00 00 00 00 00

хотя, необходимое значение находится на смещении 14 (41 64 6F 62). Значит, что-то неправильно...

Sergeos
Начинающий
Начинающий
 
Сообщения: 8
Зарегистрирован: 17.01.2005 (Пн) 2:04

Сообщение Sergeos » 27.01.2005 (Чт) 2:53

все! все работает!
код следующий (полный):
----------------------
Sub superFinder()
Dim arrDch, K As Byte
Dim ch As Byte
Dim EOF As Long
Dim i As Long

arrDch = Array(65, 100, 111, 98) 'ищем Adob
EOF = FileLen("c:\shape.bin")
Open "c:\shape.bin" For Binary As 1
K = Empty
ListBox1.Clear

For i = 1 To EOF
Get #1, , ch
If arrDch(K) = ch Then
K = K + 1
Else
K = 0
If arrDch(K) = ch Then K = K + 1
End If
If K > UBound(arrDch) Then
ListBox1.AddItem (i - K)
K = Empty
End If
Next i

Close #1
End Sub
-------------------------------
вот! может быть по данному коду есть советы по оптимизации?

Vitaly1
Брехман
Брехман
 
Сообщения: 1578
Зарегистрирован: 30.12.2002 (Пн) 16:35
Откуда: Russia, Mosсow

Сообщение Vitaly1 » 28.01.2005 (Пт) 17:00

UBound(arrDch) замени на типизированную целочисленную переменную, например перед циклом сделай:
N = UBound(arrDch)
а в цикле сравнивай с N, что бы в цикле не тратилось время на вызов функции.


Вернуться в VBA

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

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

    TopList