Newsgroup: it.comp.lang.visual-basic
Titolo: [?] Indicizzazione file di testo

Quesito forse banale, ma evidentemente non conosco i termini corretti e 
non sono riuscito a trovare info nei soliti posti.
Devo gestire circa 20-30000 record su file/s di testo, una banale 
applicazione che prevede l'inserimento di un codice articolo, l'avvio di 
una applicazione di stampa etichette che recuperera' i valori di alcuni 
campi dal file di testo.
Non posso usare database o ocx.
Per non dover cercare il codice articolo tra 20000 record in un file di 
testo (tempi biblici) ho pensato di suddividere i record in piu' file 
usando un algoritmo di hash. In fase di generazione dei dati faccio lo 
hash sul codice articolo ed aggiungo il record ad un file che ha lo 
stesso nome dello hash. Es.
Codice art: ab123
hash: 34563
Aggiungo al file 34563.txt il record corrispondente ad ab123
In questo modo i tempi di ricerca dei record si riducono drasticamente.
Fin qui tutto ok.
Allora mi sono detto: sarebbe carino poter implementare anche 
l'autocompletamento durante l'inserimento del codice articolo, ma il mio 
metodo di cui sopra ovviamente non funziona piu'.
Esiste qualche metodo piu' furbo del mio che permetta sia di avere tempi 
di ricerca bassi sia di avere la funzione di autocompletamento.
grazie
	maxx
-- 
NOSPAM: Rimuovere i trattini dallo username!
Cut hyphens from my username!

 Aggiungo al file 34563.txt il record corrispondente ad ab123
Mi sfugge il motivo di calcolare l'hash: non potevi semplicemente farti il
file ab123.txt?
Comunque ricordo che il mio rudimentale sistema di indicizzazione record
usato in un mio vecchio progettino (qualcuno si ricorda di SiDB?) univa le
tecniche delle doppia lista linkata e della ricerca dicotomica e le
prestazioni su poche migliaia di record (10/20mila) non aveva niente da
invidiare a motori DB come Access.
Per spiegartelo precisamente dovrei scartabellare nel codice che non guardo
più da tempo.
Se vuoi dare un occhio all motore te lo posso inviare per email completo di
un mini editor simil-access, che però, dato che mi stavo scrivendo una
griglia dati mia, che non funziona :),  l'IDE rimane attualmente pressochè
inutilizzabile, anche se il codice per la creazione è un simil-sql, ad es.
per creare una tabella
    Dim Server As SiDBServer
    Set Server = New SiDBServer
    ' Creo un database (una cartella nella quale staranno i file delle
tabelle)
    Call Server.Engine.ExecSiQL("create_db(" & DBName & ")")
    ' Creo la tabella senza campi/rimuovo tutti i campi di una tabella
esistente
    Call Server.Engine.ExecSiQL("restruct(" & DBName & "\" & TableName & ")
clear_fields()")
    ' Aggiungo un campo boolean
    Call Server.Engine.ExecSiQL("restruct(" & DBName & "\" & TableName & ")
add_field(Key, Boolean)")
    ' Aggiungo un campo string
    Call Server.Engine.ExecSiQL("restruct(" & DBName & "\" & TableName & ")
add_field(Name, String, 32)")
    ' Aggiungo un campo integer
    Call Server.Engine.ExecSiQL("restruct(" & DBName & "\" & TableName & ")
add_field(Size, Integer)")
    ' Imposto come chiave *non* univoca ordinata i campi Name e Key
    Call Server.Engine.ExecSiQL("restruct(" & DBName & "\" & TableName & ")
set_key(Name, Key)")
Se riesco a sistemare l'ide mando tutto al sito comune :)
Ciao
--
Reporting tool: 
http://www.neodatatype.net
Qualunque mentecatto può scrivere codice che un computer possa capire.
I buoni programmatori scrivono codice che gli uomini possano capire.
[Martin Fowler]

 per creare una tabella
Prova a mandarmelo. Vedo se riesco a capire qualcosa. Come al solito non 
ho molto tempo.


     maxx
Andrea

 ho molto tempo.
Ti invio il tutto


 
Grazie.


 
Vedi sopra.


     maxx
Andrea

 di testo (tempi biblici)
30000 record non mi sembrano molti, anzi...
Se invece che file di testo usi file random, utilizzando una type
e creando un tuo formato record in cui uno dei campi sia il tuo
codice articolo, sei sicuro che i tempi siano biblici ?
Se il file non č ordinato, leggi tutti i record memorizzando in un
array il campo che ti interessa, poi con una ricerca sequenziale
te la cavi molto piů in fretta di quel che pensi, a meno che il
computer non sia "a carbonella". Simulando, ho trovato tempi
di uno o due decimi di secondo. Se poi il file č ordinato, potresti
implementare una ricerca ad albero binario, te la cavi con 7-8
confronti fra stringhe al massimo.
Se vuoi posso postare un esempio.
Perň... ho idea di non aver capito bene il problema :-)
Bye, G.

 codice articolo, sei sicuro che i tempi siano biblici ?
Io non posso decidere il formato del file. Il formato e' testo con i 
campi separati da ';'
Io piloto un programma tramite ActiveX ed il programma non prevede un 
"metodo" di ricerca di un campo all'interno del file.
Per trovare un articolo devo quindi scorrere record per record il file 
usando i metodi esposti dall'ActiveX (db.movenext o db.moveprevious). Ed 
i tempi sono purtroppo biblici. :-(
grazie lo stesso


 ha scritto


 :)
Lui potrebbe fare lo stesso con te! ;-)
100-200 bytes
Attendo sviluppi da parte tua. :-)


> :)
uff... per questa volta ti sei salvato perche` avevo il killfile
pieno e perche' stasera ho l'interfaccia grafica :-P
-- 
ciao, hal

 pieno e perche' stasera ho l'interfaccia grafica :-P
io invece ho un'interfaccia di interbronzo :P
ciao, j.afef

 Attendo sviluppi da parte tua. :-)
sviluppi non giurarci :) diciamo ragionamenti.
vado un po' a ruota libera, non sono sicuro di aver capito.
dunque, al massimo 6 mega in tutto.
con richieste cosi' basse, io il disco lo toccherei solo una volta per
leggerlo. poi stai in ram.
non so se ricordi un test che avevamo fatto qui per misurare quante righe e'
un txt.
http://www.sundaysw.com/sw/cod_file_lines
provato ora con un file di 30k righe di ca 100 byte, con l'fso sai
esattamente quante righe sono in 1-5 decimi. magari fai qualche test in piu'
per sicurezza.
a quel punto se usi carichi un array multidimensionale con lineinput, il
file ce l'hai in ram, e non dovresti metterci tanto.
qui pero' casca l'asino. non ho ben capito  il rapporto fra la tua lettura
dei record e l'altro programma. non puoi stampare su file i soli record che
ti interessano e far leggere all'altro il tuo file ?
scusa se non ho capito una mazza. settimana pesante.
ciao, j.

 ti interessano e far leggere all'altro il tuo file ?
...una premasticazione non sarebbe male. Ma non e' quello
che sta cercando di fare il buon emmexx?
-- 
ciao, hal

 che sta cercando di fare il buon emmexx?
si'. un buon esemplare di niusgruppus ruminans :)
ciao, j.

 si'. un buon esemplare di niusgruppus ruminans :)
e' il bello di questo enneggi` :-)
-- 
ciao, hal

 detto che tutte le righe siano lunghe uguali.
non so se avevi provato quel dirsize (oddio, non so se te l'ho mandato, in
effetti, mi sembrava di si').
oltre a risparmiare molto codice, il fso puo' essere davvero veloce. a
calcolare l'occupazione di una dir ci mette un bel po' di meno che a usare
un dir ricorsivo.
imho, ma molto molto a sensazione, fa delle chiamate (oltre che a redmond a
carico nostro :) direttamente al s.o. che a vb non sono permesse.
non mi piace usarlo a sproposito, come a giudicare da certi post mi sembra
un po' si rischi, ma un po' di piu' vorrei conoscerlo.
ce ne saranno molti altri, cmq un buon sito mi era sembrato
http://www.sloppycode.net/Reference/FSO/
ciao, j.

 
http://www.sloppycode.net/Reference/FSO/
grazie, aggiunto ai bookmarks :-)
-- 
ciao, hal

 buona per un po' di sano hacking ;-)
adesso ti metti comodo e mi spieghi cos'hai intenzione di fare a un exe vb
con linux. o stai barando e usi vmware ? :)
a prop, se non te li ho gia' mandati ti mando i sorgenti del dirsize.
circa 20 righe :)
se penso che c'e' chi vuole sapere se abbiamo scritto abbastanza=molte righe
di codice, kloc, come le chiamano loro...
alloc. no il c non c'entra: e' come li chiamo io :)

 alloc. no il c non c'entra: e' come li chiamo io :)
si tratta di farci il calloc :-)
-- 
ciao, hal

 mandi mandi che mi facilita il lavoro ;-)
mandato
ciao, j.

 scusa se non ho capito una mazza. settimana pesante.
Non dirlo a me...
Come ho gia' detto in altre risposte il collo di bottiglia non e' la 
lettura del file, ma la necessita' di far leggere il file ad un activeX 
di una applicazione. Questa applicazione non ha una funzione di ricerca 
dei record e possiede solo i metodi movenext e moveprevious per 
spostarsi all'interno del file di testo.
il ciclo:
do while not db.eof
    if db.campo="pippo" then
       db.stampa_il_record
    endif
    db.movenext
loop
impiega 100 secondi per 1000 record
La necessita' primaria e' quindi spezzettare il file completo in tanti 
file che contengano al massimo un centinaio di record.
Sino a qui non ci sono problemi.
Il funzionamento dell'applicazione e' molto banale:
in una casella di testo viene inserito un codice articolo, in un'altra 
la quantita' da stampare e si preme un pulsante che stampa.
Attraverso il ciclo di cui sopra viene cercato il record corrispondente 
al codice articolo e se viene trovato viene avviata la stampa.
A questo punto volevo implemetare anche un meccanismo di 
autocompletamento del codice articolo, ma con lo schema di hashing 
ovviamente non funziona: lo hash su una parte del codice articolo e' 
diverso da quello sull'intero codice.
In realta' adesso mi viene in mente che io potrei creare un file 
parallelo contenente solo codice articolo e hash. Quando viene inserito 
un codice parziale effettuo prima la ricerca nel mio file indice 
proponendo il primo codice che ha una parziale corrispondenza.
Mi sa che mi sono complicato inutilmente la vita tentando di legare 
autocompletamento e hash. Meglio tener separate le 2 cose.
Grazie a tutti per aver insistito con i vani suggerimenti di lettura del 
file (che mi sembravano non c'entrare nulla con la mia richiesta).
Repetita juvant!


 Ed i tempi sono purtroppo biblici. :-(
Ma puoi fargli fare anche una seek, uno spostamento ad un record
specifico, spero ?
In questo caso, leggi il file direttamente, così scavalchi il problema:
metti in una matrice il campo che ti serve e cerchi in quello, sia pure
sequenzialmente, in pochi decimi o magari centesimi di secondo.
' ****************
Sub VecchiaImportaDaCSV(NomeFileCSV)
    Dim FileLibero As Integer
    Dim tempStringa As String
    Dim testStringa
    Dim Indice As Long
    FileLibero = FreeFile
    Open NomeFileCSV For Input As #FileLibero
    Line Input #FileLibero, tempStringa
    Indice = 0
    Do While Not EOF(FileLibero)
        Line Input #FileLibero, tempStringa
        testStringa = Split(tempStringa, ";", , vbTextCompare)
        Debug.Print "Linea Letta:"
        Debug.Print tmpStringa
        Debug.Print "Singoli campi:"
        For N = 0 To UBound(testStringa)
            Debug.Print N, testStringa(N)
        Next N
        Indice = Indice + 1
        ' una volta che hai scoperto qual è il campo
        ' che ti serve, puoi eliminare la parte di debugging
        ' e attivare la riga seguente
        ' TuaMatrice(Indice) = testStringa(Numerodelcampochetiserve)
    Loop
    Close FileLibero
    Debug.Print "Linee lette: " & Indice
End Sub
' ****************
Bye, G.

 in piu' per sicurezza.
FSO: lines: 10000 -- time: 0,063
LINEINPUT: lines: 10000 -- time: 0,047 <----------- :-P
REPLACE: lines: 10000 -- time: 0,328
SPLIT: lines: 10000 -- time: 0,219
VBCRLF: lines: 10000 -- time: 0,117
Bye, G.

 VBCRLF: lines: 10000 -- time: 0,117
:)
in questo caso, l'importante e' che *la split* vada piu' piano :)
dalla via che sei li', prova anche con molte piu' linee. mi sembra che alla
lunga il fso fosse il più stabile come medie. ovviamente se mentre usi
lineinput il computer e' libero, e mentre usi il fso salvi un psd da 980 mb,
la prova e' dubbia :)
ciao, j.

 mentre usi il fso salvi un psd da 980 mb, la prova e' dubbia :)
Ho anche (ORRORE !) disattivato l'AV, il FW e tutto il resto :-)
Una cosa da dire è che anche compilando, con tutte le ottimizzazioni
possibili, le differenze rispetto al programma che gira nell'IDE
sono minime.
Una cosa ancora più strana è che disattivando tutto quello
che gira in background, AV, FW, Seti, OE/IE, insomma_tutto_,
le prove dell'FSO sono effettivamente più veloci, anche se
di poco, ma incredibilmente le prove con la LI sono risultate
più _*LENTE*_.
Bye, G.

 più _*LENTE*_.
fai questo, apri quello, disattiva quest'altro. *dovrebbe* accadere che...
computer science -- noi amiamo le certezze :)
ciao, j.
(*) mando posta

 
Il problema non e' la lentezza nella ricerca dei record, che ho risolto 
suddividendo il file completo in file piu' piccoli in modo da mantere 
"veloce" il ciclo con la db.movenext.
Come ho scritto rispondendo a j., ho tentato di complicarmi inutilmente 
la vita cercando di utilizzare lo stesso meccanismo per gestire sia la 
ricerca di un record che l'autocompletamento durante la digitazione del 
codice articolo. Tenendoli separati il problema non sussiste:
- per "stampare" un record uso il meccanismo che ho scritto sopra.
- per l'autocompletamento leggo un file (o lo carico in memoria) che 
contiene l'elenco dei codici articolo e che viene letto istantaneamente.
grazie


 computer science -- noi amiamo le certezze :)
"Ameremmo", almeno sotto Win. Non stranamente, sotto *x ne
ho molte di più...
Bye, G.

 No, altrimenti non avrei postato questo "problema".
Ommaigodd. Hai un modo di fare del male a chi lo ha scritto, almeno ?
Bye, G.

Il 27/02/2005 0.33, Paperino scrisse:

Pubblicare il link al programma?
http://www.teklynx.com/products/labels/codesoft_detail.html


 Pubblicare il link al programma?
+ 5 punti BI (Bastard Inside) per il signore ;-)
Bye, G.

Il 27/02/2005 21.09, Paperino scrisse:

Solo 5??? :-(
;-)
