[vb] Zoeken naar keyword in bestand

Pagina: 1
Acties:
  • 116 views sinds 30-01-2008
  • Reageer

  • KO
  • Registratie: December 2001
  • Laatst online: 12-11-2023
Ik moet dus in een bestand zoeken naar keywords.

Weet iemend een snellere methode dan een bestand openen, regel voor regel lezen en met de functie instr(bla, bla) zoeken i/d regel naar het keyword? :?

Yesterday Is History. Today Is A Gift. Tomorrow Is Mystery


  • Limhes
  • Registratie: Oktober 2001
  • Laatst online: 09-04 16:10

  • KO
  • Registratie: December 2001
  • Laatst online: 12-11-2023

Yesterday Is History. Today Is A Gift. Tomorrow Is Mystery


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 04-05 14:55

Janoz

Moderator Devschuur®

!litemod

Hoe had je zelf gedacht dat dit anders zou kunnen werken? Stel je zou een VB functie 'strinfile(bla,bla)' hebben, hoe dacht je dat deze dan geimplementeerd zou zijn?

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • KO
  • Registratie: December 2001
  • Laatst online: 12-11-2023
Misschien is er een API call oid?
Windows heeft tenslotte ook een "zoeken in" functie

[ Voor 45% gewijzigd door KO op 02-10-2003 10:17 ]

Yesterday Is History. Today Is A Gift. Tomorrow Is Mystery


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 04-05 14:55

Janoz

Moderator Devschuur®

!litemod

En hoe denk je dat die API call dan geimplementeerd is?

Wat ik alleen maar wil zeggen is dat er (zonder dat je gebruik gaat maken van caching oid) geen snellere manier is dan degene die je opnoemt. Om te kijken of een woordje in een bestand zit zul je de computer elk woordtje in het bestand moeten laten controleren. Je kunt het natuurlijk wel ietsje versnellen door wat grotere blokken in te lezen dan alleen een regel, maar in principe komt het dan nog steeds op hetzelfde neer. Of het nu in je eigen programma gebeurt of doordat je een API call aanroept.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • Limhes
  • Registratie: Oktober 2001
  • Laatst online: 09-04 16:10
KO schreef op 02 October 2003 @ 10:01:
[...]


In een bestand, niet naar....
Als het in VBA zit, zal het met VB toch ook wel kunnen. Kijk eens naar de hele thread, en zie ergens Application.FileSearch staan. Dit is wat het daar in feite doet.

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Effe in het kort:

1) Open een bestand binair
2) Vul een string met String(Lof(bestand),chr(0))
3) Get die string
4) If instr(myStr,"zoek")>0 then gevonden
5) Close bestand...

Ik zal zometeen effe een voorbeeldje in elkaar flansen...

/edit/
Bij deze dus :

Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Public Function FindStringInFile(strFile As String, strFind As String, Optional iCompareMethod As VbCompareMethod = vbTextCompare) As Long
    Dim FF As Integer
    Dim strTMP As String
    Dim lRes As Long
    
    lRes = -1                       'Initialiseer return waarde
    If Len(Dir(strFile)) > 0 Then   'Bestaat het bestand?
        FF = FreeFile               'Vraag een vrije filehandle aan
        Open strFile For Binary As #FF
        strTMP = String(LOF(FF), Chr(0))    'Initialiseer temp string op lengte van bestand met 0-en
        Get #FF, , strTMP                   'Lees het hele bestand in de string
        Close #FF
        lRes = InStr(1, strTMP, strFind, iCompareMethod)    'Zoek naar het zoekwoord
    End If
    FindStringInFile = lRes         'Geef resultaat terug
End Function


Geeft eerste positie terug van plaats van gevonden keyword, -1 als bestand niet bestaat, 0 als niet gevonden. Dus als het resultaat > 0 dan komt het zoekwoord voor...

Aanroep voorbeeldje:
Visual Basic:
1
    Debug.Print FindStringInFile("C:\MijnMap\MijnSubmap\Mijnbestand.doc", "zoekdit")


Overigens is er een 3e optionele parameter om aan te geven HOE je wil zoeken:
• Binary compare = Case sensitive
• Text compare = Case in-sensitive

That's it... Voorgekauwd en wel ;) Excuses voor de layout

Enkele kanttekeningen:
• Pas op met grote bestanden (je leest ze compleet in het geheugen in!). Is op te lossen door in blokken van (zeg) 1 meg te lezen
• Errorhandling mag je zelf doen
• Binaire bestanden, in tegenstelling tot ascii-files, willen nog wel eens unicode strings bevatten. In dat geval moet je na iedere char in je string een nul-char toevoegen. Wellicht dat je dan alsnog gewoon vindt wat je zoekt.

[ Voor 102% gewijzigd door RobIII op 02-10-2003 10:40 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Verwijderd

Ja dus gewoon het hele bestand in een string zetten en dan met instr zoeken...

Zoals hierboven.... :P

[ Voor 15% gewijzigd door Verwijderd op 02-10-2003 10:35 ]


  • KO
  • Registratie: December 2001
  • Laatst online: 12-11-2023
RobIII schreef op 02 October 2003 @ 10:25:[...]
That's it... Voorgekauwd en wel ;) Excuses voor de layout
+1 Bijzonder aardig

Yesterday Is History. Today Is A Gift. Tomorrow Is Mystery


Verwijderd

Ik zal het wel niet helemaal snappen hoor, maar je kan onder zoeken ook zoeken in bestand. Dan zoekt hij het woord in elk bestand. Dat neemt ff tijd maaar jah. Het werkt wel

  • KO
  • Registratie: December 2001
  • Laatst online: 12-11-2023
Verwijderd schreef op 02 oktober 2003 @ 10:46:
Dat neemt ff tijd maaar jah. Het werkt wel
Precies, maar bij bestanden die minimaal 50mb tot 120 mb zijn en waarin meerdere keren per dag gezocht moet worden wordt jij niet vrolijk als dat ff tijd neemt....en er hangt een boze klant aan de lijn..... :Y)

Yesterday Is History. Today Is A Gift. Tomorrow Is Mystery


  • PipoDeClown
  • Registratie: September 2000
  • Niet online

PipoDeClown

Izze Zimpell

KO schreef op 02 October 2003 @ 10:54:
[...]
Precies, maar bij bestanden die minimaal 50mb tot 120 mb zijn en waarin meerdere keren per dag gezocht moet worden wordt jij niet vrolijk als dat ff tijd neemt....en er hangt een boze klant aan de lijn..... :Y)
in zo'n geval is het misschien verstandig erbij te vertellen wat voor type bestand het is, het doel ervan en bijv. om hoeveel woorden het gaat etc.

God weet alles, want hij is lid van de Mosad. To protect your freedom i will take that away from you. Mijn drankgebruik heeft ernstig te lijden onder mijn gezondheid.


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
KO schreef op 02 October 2003 @ 10:54:
[...]


Precies, maar bij bestanden die minimaal 50mb tot 120 mb zijn en waarin meerdere keren per dag gezocht moet worden wordt jij niet vrolijk als dat ff tijd neemt....en er hangt een boze klant aan de lijn..... :Y)
Hehe ;) Dat verwachtte ik al :Y)

Bij deze dus een aangepaste versie die wat geheugenvriendelijker is ;)
Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Public Function FindStringInFile(strFile As String, strFind As String, Optional iCompareMethod As VbCompareMethod = vbTextCompare) As Long
    Dim FF As Integer
    Dim strTMP As String
    Dim lRes As Long
    Dim lSize As Long
    Dim lMaxBlocks As Long
    Dim lBlockCount As Long
    Dim lRest As Long
    
    Const cMaxBlockSize = &H100000  'Max blokken van 1 meg
    
    lRes = -1                       'Initialiseer return waarde
    lBlockCount = 0                 'Aantal gelezen blokken
    If Len(Dir(strFile)) > 0 Then   'Bestaat het bestand?
        FF = FreeFile               'Vraag een vrije filehandle aan
        Open strFile For Binary As #FF
        lSize = LOF(FF)             'Grootte van bestand uitlezen
        lMaxBlocks = lSize \ cMaxBlockSize                      'Opdelen in x aantal blokken
        lRest = lSize - (lMaxBlocks * cMaxBlockSize)            'Hoeveel bytes blijven er over in het laatste blok?
        strTMP = String(cMaxBlockSize, Chr(0))                  'Initialiseer temp string op lengte van bestand met 0-en
        While Not EOF(FF) And (lRes < 1) And (lBlockCount < lMaxBlocks) 'Zoek door het hele bestand, of totdat we iets gevonden hebben
            Get #FF, , strTMP                                   'Lees een blok in de string
            lRes = InStr(1, strTMP, strFind, iCompareMethod)    'Zoek naar het zoekwoord
            lBlockCount = lBlockCount + 1                       'Tel gelezen blok
        Wend
        If (lRest > 0) And (lRes < 1) And (Not EOF(FF)) Then    'Lees rest als nodig
            strTMP = String(lRest, Chr(0))                      'Vul string ter grootte van de rest
            Get #FF, , strTMP                                   'Lees laatste loodjes ;-)
            lRes = InStr(1, strTMP, strFind, iCompareMethod)    'Zoek naar het zoekwoord
        End If
        Close #FF
    End If
    FindStringInFile = lRes         'Geef resultaat terug
End Function


* RobIII heeft niks beters te doen :+

Nog meer opmerkingen:
• Binary compare is *sneller*!!
• Blokgrootte kun je wat mee spelen, kleiner of misschien groter kan betere prestaties leveren

Overigens vind ik dit 1 van de mooiere oplossingen onder (native) VB. Ik weet wel bijna zeker dat de WinAPI je voorziet van mooiere (lees: snellere) oplossingen, maar daar ben ik nu toch echt effe te druk voor. Je zult het hier effe mee moeten doen ;)

Overigens, als je vaker zoekt is de Indexing service misschien eens iets waar je eens naar moet kijken B)

[ Voor 41% gewijzigd door RobIII op 02-10-2003 11:22 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • KO
  • Registratie: December 2001
  • Laatst online: 12-11-2023
* KO zegt RobIII for president

Het (test) bestand bestaat 15000 regels en is iets van 50 mb (er zijn nog grotere bestanden)

Zelf heb ik dit gemaakt, ik heb het topic ff een uurtje niet gevolgd :7

Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Set fi = FSO.GetFile(strInvoerBestand)
FileBuffer = fi.Size
    
Set fi = Nothing
    
Set fIn = FSO.OpenTextFile(strInvoerBestand)
b = fIn.Read(FileBuffer)

If InStr(1, b, strFactuurnummer) > 0 Then
        ' Startpositie van het gevonden factuurnummer
        startPos = InStr(1, b, strFactuurnummer)
        ' Einde positie factuur bepalen
        lengteToEindPos = InStr(startPos, b, KENMERK_EINDE_FACTUUR) + Len(KENMERK_EINDE_FACTUUR)
        ' Dan hebben we de lengte van de factuur vanaf factuurnummer
        lengteFactuur = lengteToEindPos - startPos
        ' Dus terug zoeken naar het begin van de factuur
        startPosfactuur = InStrRev(b, KENMERK_BEGIN_FACTUUR, startPos)
        ' Dit suktje moet er nog aan geplakt worden bij de startpositie
        lengtePlus = startPos - startPosfactuur
        ' Een nieuwe start positie van de hele factuur
        nieuweStartPos = startPos - lengtePlus
        
        
        Debug.Print Mid$(b, nieuweStartPos, lengteFactuur + lengtePlus)
        
    End If


Het zijn dus facturen waarvan een preview op het scherm getoond moet worden.
Het bestand delen in blokken is ook een goede tip

[ Voor 8% gewijzigd door KO op 02-10-2003 12:36 ]

Yesterday Is History. Today Is A Gift. Tomorrow Is Mystery


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Er is overigens nog een gevaar (had ik niet meteen voorzien, maar bedenk het nu pas):
Als je een bestand in blokken "hakt", kan het zijn dat je zoektekst nét in 2 blokken ofzo valt. In dat geval zul je dus niets vinden... :(

Je kunt dit oplossen door te zorgen dat je blokken minimaal len(strZoek) overlappen.... Maar dat mag je zelf doen :)

Oh, en nogmaals: Ik gebruik dus in mijn voorbeelden Native VB, geen API's of FSO's. Beide hebben vast mooiere methodes voor je probleem...

[ Voor 19% gewijzigd door RobIII op 02-10-2003 13:02 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • KO
  • Registratie: December 2001
  • Laatst online: 12-11-2023
RobIII schreef op 02 October 2003 @ 13:00:
Oh, en nogmaals: Ik gebruik dus in mijn voorbeelden Native VB, geen API's of FSO's. Beide hebben vast mooiere methodes voor je probleem...
API's kan ik niet vinden, misschien is er iemand hier met nog een goede tip?
Met fso kan je niet echt zoeken in een bestand.

Yesterday Is History. Today Is A Gift. Tomorrow Is Mystery


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
KO schreef op 02 oktober 2003 @ 13:04:
[...]
API's kan ik niet vinden, misschien is er iemand hier met nog een goede tip?
Met fso kan je niet echt zoeken in een bestand.
Heb me nog effe uitgeleefd ;)

• Mooie class van gemaakt
• Programmaatje omheen gebouwd
• In zipje gegooid (inc. source dus)
Online gegooid voor je ;)

De class heeft de volgende events:

• BeforeSearchStart(Path As String, FileSpecs As String, Recursive As Boolean) : Treedt op voordat er daadwerkelijk door alle directory's wordt geragd
• ChangeDirectory(Path As String) : Treedt op als er van directory gewisseld wordt
• Filematch(Path As String, FileName As String) : Treedt op als een bestand voldoet aan de filespecs
• SearchDone() : Treedt op als de zoekactie voltooid is
• ErrorOccured(ErrorNumber As Long, Description As String) : Treedt nooit op :Y)
• BeforeFileOpen(Path As String, FileName As String) : Treedt op voordat een bestand wordt geopend om naar de zoektekst te zoeken
• AfterFileClose(Path As String, FileName As String) : Treedt op als het zoeken in het bestand naar de zoektekst voltooid is
• BlockRead(CurrentBlock As Long, TotalBlocks As Long) : Treedt op als er een block wordt gelezen (handig voor progressbars etc)

Methods:

• CancelSearch : Breekt alle zoekacties af
• FindStringInFile(strPath As String, strFileName As String, strFind As String, Optional iCompareMethod As VbCompareMethod = vbTextCompare) : Ken je reeds ;)
• Search(strRoot As String) : Doorzoekt alle mappen vanaf strRoot naar bestanden die voldoen aan FileSpecs

Properties:

• BlockSize : Zet of lees de blocksize (default 1Mb) die wordt gebruikt in FindStringInFile
• FileSpecs : Zet of lees de filespecs (default "*.*") waar de bestanden aan moeten voldoen. Filespecs voorbeelden zijn "*.htm" of "*.txt;*.doc"
• Exclude : De FileSpecs worden excluded (defaut False), dus alle bestanden die er niet aan voldoen worden doorzocht
• RecursiveSearch : De directory wordt recursief doorzocht (default True), anders alleen de directory zelf

Veel plezier ermee.... Mag ik nu gaan lunchen? :+

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • KO
  • Registratie: December 2001
  • Laatst online: 12-11-2023
Ziet er goed uit _/-\o_ Eet ze :)

Yesterday Is History. Today Is A Gift. Tomorrow Is Mystery


  • Yoeri
  • Registratie: Maart 2003
  • Niet online

Yoeri

O+ Joyce O+

(overleden)
er bestaat iets als Microsoft Indexing Server (gratis bij .....)

daarmee kun je perfect doen wat je wilt, héééél snel woorden en complexe zoektermen zoeken IN een bestand

ook vanuit VB, VBA, whatever

[ Voor 9% gewijzigd door Yoeri op 02-10-2003 13:55 ]

Kijkje in de redactiekeuken van Tweakers.net
22 dec: Onze reputatie hooghouden
20 dec: Acht fouten


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Robbedoeske schreef op 02 October 2003 @ 13:55:
er bestaat iets als Microsoft Indexing Server (gratis bij .....)

daarmee kun je perfect doen wat je wilt, héééél snel woorden en complexe zoektermen zoeken IN een bestand

ook vanuit VB, VBA, whatever
Le-zen ;)
RobIII schreef op 02 October 2003 @ 11:15:
[...]
<knip>
Overigens, als je vaker zoekt is de Indexing service misschien eens iets waar je eens naar moet kijken B)

[ Voor 3% gewijzigd door RobIII op 02-10-2003 14:22 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • KO
  • Registratie: December 2001
  • Laatst online: 12-11-2023
Robbedoeske schreef op 02 October 2003 @ 13:55:
er bestaat iets als Microsoft Indexing Server (gratis bij .....)

daarmee kun je perfect doen wat je wilt, héééél snel woorden en complexe zoektermen zoeken IN een bestand

ook vanuit VB, VBA, whatever
Heb je voorbeeld of url om dit vanuit vb te benaderen?

Yesterday Is History. Today Is A Gift. Tomorrow Is Mystery


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
KO schreef op 02 October 2003 @ 15:06:
[...]


Heb je voorbeeld of url om dit vanuit vb te benaderen?
Google is je vriend ;)

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij

Pagina: 1