Autore Topic: Concatenazione di stringhe  (Letto 1857 volte)

Offline milio

  • Senatore Gambero
  • ******
  • Post: 1.268
  • Chi parla poco dice tanto...
    • Mostra profilo
Concatenazione di stringhe
« il: 21 Luglio 2010, 00:06:40 »
Ciao a tutti.
Volevo rendervi partecipi di una mia piccola 'scoperta' sulla concatenazione delle stringhe...

E' da un paio di giorni che, dopo aver messo a nanna i le mie due creature  :sleepy: , lavoro ad un progettino per visualizzare statistiche riguardante dati generati da un anemometro.
Il suddetto anemometro, tramite un plc, salva i dati ogni secondo su compact flash in un file csv, indicando data ora, velocita', qualita' del segnale....
Ora il mio problema iniziale era questo: la data nel file csv aveva un formato del tipo dd/mm/yy hh:nn:ss, che importandolo successivamente in un db sqlite con il seguente codice sqlite3

Codice: [Seleziona]
paolo@hpmilio:~$ sqlite3 eolico.db
SQLite version 3.6.22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .separator "\t"
sqlite> .import file.csv log_anemometro
sqlite>

mi rendeva impossibile, all'interno di gambas, creare delle query specificando appunto il periodo di lettura.
A questo punto ho creato una funzione che sostituiva la data incriminata in un formato corretto e allo stesso tempo scriveva in una stringa le insert per accodare i record nella tabella del db:

Codice: vb [Seleziona]
Public Sub Load(Path As String)
Dim Nx As Integer
Dim Rec As New String[]
Dim Fields As New String[]

  $Txt = File.Load(Path)
  Rec = Split($Txt, "\n", "", True)
  $Query = "BEGIN;" & Chr(10)
  For Nx = 0 To Rec.Max
    Fields = Split(Rec[Nx], "\t")
    $Query &= "INSERT INTO log_anemometro (data,valore,qualita) VALUES ('" & Format$(CDate(Val(Fields[0])), "yyyy-mm-dd hh:nn:ss") & "'," & Fields[1] & "," & Fields[2] & ");" & Chr(10)
    ArrayCsv.Add(Fields.Copy())
  Next
  $Query &= "END;"

End


Con questo codice, con un Rec.Max = 64000, mi rallentava di molto il programma, arrivando a tempi di attesa di oltre due minuti...
Provando ripetutamente a modificare il codice e dopo svariate ore  :hatecomputer: , sono finalmente arrivato alla soluzione:

Codice: vb [Seleziona]
Public Sub Load(Path As String)
Dim Nx As Integer
Dim Rec As New String[]
Dim Fields As New String[]
Dim FileTemp As Stream

  $Txt = File.Load(Path)
  Rec = Split($Txt, "\n", "", True)
  FileTemp = Open User.Home &/ "eolico.sql" For Create
  Print #FileTemp, "BEGIN;"
  For Nx = 0 To Rec.Max
    Fields = Split(Rec[Nx], "\t")
    Print #FileTemp, "INSERT INTO log_anemometro (data,valore,qualita) VALUES ('" & Format$(CDate(Val(Fields[0])), "yyyy-mm-dd hh:nn:ss") & "'," & Fields[1] & "," & Fields[2] & ");"
    ArrayCsv.Add(Fields.Copy())
  Next
  Print #FileTemp, "END;"
  FileTemp.Close()
  $Query = File.Load(User.Home &/ "eolico.sql")

End


Come potete notare, la formattazione della data e la creazione della stringa di insert e' uguale alla prima funzione.
Ma con questo sistema ho utilizzato un file esterno ("eolico.sql") per scrivere le varie insert e, una volta finito il ciclo, ho carico la variabile stringa $Query con il file appena creato.
Bene, il tempo di attesa adesso si e' ridotto a soli due secondi!   8)

Spero che questa mia esperienza possa essere di aiuto a chi fa utilizzo massiccio di concatenazioni di stringhe.
Ciao ciao....
« Ultima modifica: 21 Luglio 2010, 20:40:28 da milio »

Offline md9327

  • Moderatore
  • Senatore Gambero
  • *****
  • Post: 2.840
    • Mostra profilo
Re: Concatenazione di stringhe
« Risposta #1 il: 21 Luglio 2010, 10:50:45 »
Perdona, ma la variabile "X" nel for-next, da dove proviene ?

Ti ricordo che le variabili dichiarate, ma non impostate, possono contenere valori casuali, anche se la documentazione ufficiale dichiara il contrario.

Offline milio

  • Senatore Gambero
  • ******
  • Post: 1.268
  • Chi parla poco dice tanto...
    • Mostra profilo
Re: Concatenazione di stringhe
« Risposta #2 il: 21 Luglio 2010, 20:40:09 »
Si hai ragione, chiedo umilmente scusa  :-[ ma la sub conteneva anche altro codice che ho 'ripulito' prima di postare...
Non sono mai stato bravo a far pulizia  ;D
Correggo subito il post, onde evitare incomprensioni...

Offline md9327

  • Moderatore
  • Senatore Gambero
  • *****
  • Post: 2.840
    • Mostra profilo
Re: Concatenazione di stringhe
« Risposta #3 il: 22 Luglio 2010, 10:33:18 »
Bè, l'appunto l'avevo fatto, supponendo un errore da quelle bande, ma evidentemente non è così.

Devo provare la cosa, ma presumo che il problema sia la routine interna della gestione delle stringhe. Tieni conto che, lavorando in C/C++, l'utilizzo degli oggetti String, invece dei classici "char *", hanno tempi di manipolazione che possono arrivare a 100:1.
Per intenderci, in C++, String come anche in Gambas è un oggetto (o classe, come desideri), mentre l'elementare "char" è una posizione fisica in memoria. Se mentre la copia, ad esempio, di due stringhe attraverso char (es. "char[0]='x'"), mettiamo un tempo di 1ms, con String può arrivare anche a 50/100ms, il che vuol dire che una applicazione con molte istruzioni di questo tipo, si potrebbe considerare OUT-OF-TIME, ovvero NO REALTIME.
Con molta probabilità, la routine interna di Gambas che, oltretutto credo si basi anche su altre librerie esterne, ha dei problemi con stringhe lunghe oltre un certo numero di caratteri, superiore addirittura al tempo di accesso su disco (come da tuo test). Tieni anche conto che le String in Gambas usano UTF-8 internamente, mentre non viene usato nella scrittura su disco. Per ultimo, le operazioni di concatenazione di caratteri all'interno di una STring, specialmente se questa inizia a raggiungere dimensioni ragguardevoli, sono abbastanza onerose.

Detto questo, e spero che sia riuscito a spiegarmi in qualche modo, credo che il problema sia legato a quanto scritto, a meno ci sia qualche altra cosa che il tuo spezzone di codice non riesce ad evidenziare.