Italian Compattare al massimo alcuni valori

AlpVir

Well-Known Member
Licensed User
Longtime User
Dovrei compattare al massimo i dati scritti in un file di testo, ma non zippandolo (questo perchè i dati in questione sono scritti nel file di testo ogni X secondi, aggiungendoli ai precedenti)
Il codice qui sotto scrive 2 dati (i numeri double 44.123456 e 7.123456; ma sarebbe sufficiente anche un float per descrivere i 2 valori con una sufficiente precisione) ed il file "prova.txt" occupa 19 byte. Difatti
44.123456 in formato testo occupa 9 byte;
7.123456 in formato testo occupa 8 byte;
con virgola e il CR i conti tornano.
Tuttavia so che 2 double occuperebbero 128 bits (16 bytes). Con il CR saremmo a 17 bytes. Se trovassi il modo di scrivere questi 2 double in un file di testo avrei risparmiato 2 bytes.
Se usassi i float il risparmio sarebbe ancora più consistente (4+4+1=9 a fronte di 19; risparmio 10 bytes !) ed è proprio la via che vorrei privilegiare.
Ovviamente dovrei poi essere in grado di reinterpretare, leggendo il file di testo, i corretti valori numerici.
Si può fare con gli strumenti a disposizione di B4A ?
Grazie per l'attenzione.
B4X:
Dim Lat, Lon         As Double  ' ma sarebbe sufficiente un float)
    Dim strLat,strLon    As String
    Dim Riga        As String
    Dim Ele()        As String
   
    Try
        File.delete(File.DirRootExternal,"prova.txt")
    Catch
        Log(LastException)
    End Try
   
    '--- i dati originali in double (ma sarebbe sufficiente un float)
    Lat=44.123456
    Lon=7.123456
   
    '--- converto
    strLat=Lat
    strLon=Lon
    Riga=strLat & "," & strLon

    '--- registro
    Dim TW   As TextWriter
    TW.Initialize(File.OpenOutput(File.DirRootExternal,"prova.txt",False))
    TW.WriteLine (Riga)
    TW.Close
   
    '--- azzero
    Lat=0:Lon=0:strLat="":strLon="":Riga=""
   
    '--- leggo
    Dim TR   As TextReader
    TR.Initialize(File.Openinput(File.DirRootExternal,"prova.txt"))
    Riga=TR.ReadLine
    TR.Close
   
    '--- interpreto
    Ele=Regex.Split(",",Riga)
   
    '--- visualizzo e verifico che si tratta effettivamente di numeri (aggiungendo 1)
    Lat=Ele(0)+1
    Lon=Ele(1)+1
   
    Msgbox (Lat,Lon)      
   
    '--- prova.txt occupa 19 byte (difatti 9+1+8+CR=19)
 

Star-Dust

Expert
Licensed User
Longtime User
Mi sorge subito una domanda, perché?
Quale utilità c'é nel risparmiare 10byte spazio visto che potresti perdere di più allungando il codice?
 
Last edited:

sirjo66

Well-Known Member
Licensed User
Longtime User
certo che si può fare, ma allora il file non lo devi gestire come un file di testo, ma come un file binario.
Ma oltre a quei valori che hai detto, ci sono altri dati nel file ??
Te lo chiedo perchè se ci sono solo quei valori, secondo me potresti anche non mettere il CR
 
  • Like
Reactions: udg

udg

Expert
Licensed User
Longtime User
Oltre al consiglio di @sirjo66 sul formato binario che condivido, se fornisci qualche dettaglio in più sul progetto o sulla natura dei dati forse potremmo partorire qualche idea migliore. Faccio un semplice esempio..
Ammettendo che si tratti di memorizzare costantemente delle coordinate (nessuna marca temporale?) potresti risparmiarti la registrazione di dati identici (e anche di quelli molto simili) semplicemente ignorandoli o sostituendoli con un carattere speciale. In questo modo un oggetto fermo non causa la proliferazione di dati inutili..
 

Star-Dust

Expert
Licensed User
Longtime User
Ammesso che ci sia un vantaggio nel farlo, Io userei SQLite con due campi Real oppure salvare come lista o Mappa, mai con Text.
 

AlpVir

Well-Known Member
Licensed User
Longtime User
@Star-Dust : nella mia ipotesi sono 2 byte su 19 se uso variabili double ma se uso delle float (ampiamente sufficienti per il mio caso) i byte risparmiati sono 10 su 19 (la metà !)
@sirjo66 : ci sono altri dati fra cui la quota e il tempo. Il file deve necessariamente un txt, altrimenti non passa nel web attraverso il protocollo http.
@udg: il mio progetto è alla pagina www.lalpinistavirtuale.it/sonoqui. Si tratta di inviare le coordinate geografiche e altri dati di contorno sul web. Per il momento (e la cosa funziona perfettamente) invio brevi spezzoni come questo :
44.394370, 7.519322,0, 1817,,, 11:48:38

44.394471, 7.518923,0, 1820,,, 11:48:48

44.394832, 7.519052,0, 1830,,, 11:48:58

44.395176, 7.519180,0, 1830,,, 11:49:08

44.395553, 7.519314,0, 1820,,, 11:49:18

44.395916, 7.519603,1, 1814,10000,300000, 11:49:28

44.396480, 7.519479,0, 1817,,, 11:49:38

44.397054, 7.519261,0, 1827,,, 11:49:48

44.397497, 7.518722,0, 1817,,, 11:49:58

44.397961, 7.518752,0, 1814,,, 11:50:08
ma vorrei appunto compattare questi dati.
Riguardo il risparmio quando i dati sono identici bisogna tener conto che il GPS fornisce continuamente dati variabili, se pur di poco. Vero è che potrei calcolare la distanza lineare fra 2 punti consecutivi e se essa è minore di un certa entità, considerare i due punti identici. Non so però se il gioco vale la candela visto che si tratta di monitare persone che si muovono, non che stanno ferme al bar.
 

AlpVir

Well-Known Member
Licensed User
Longtime User
Ammesso che ci sia un vantaggio nel farlo, Io userei SQLite con due campi Real oppure salvare come lista o Mappa, mai con Text.
Ci avevo pensato ma questo comporterebbe una radicale modifica al mio progetto (già funzionante) e probabilmente un maggior consumo di banda.
 

udg

Expert
Licensed User
Longtime User
persone che si muovono, non che stanno ferme al bar
Giusto, ma proprio perché non sono centometristi è naturale pensare che dopo pochi secondi siano ancora più o meno nello stesso punto. E se aggiungi che la precisione del GPS civile è quella che è, non credo che sia necessario registrare tonnellate di dati pressoché inutili.
Potresti anche semplicemente ridurre la frequenza di acquisizione dei dati GPS (riducendo il consumo di batteria, tra le altre cose).
 

Star-Dust

Expert
Licensed User
Longtime User
Ci avevo pensato ma questo comporterebbe una radicale modifica al mio progetto (già funzionante) e probabilmente un maggior consumo di banda.
Cos'è un applicazione che verifica i camerieri di un bar stiano lavorando anziché imboscarsi in cantina?
 
Last edited:

AlpVir

Well-Known Member
Licensed User
Longtime User
@udg : non sono tonnellate di dati ma solo chili; se però c'è da risparmiare ... ben venga. La frequenza di acquisizione dei dati è regolabile da 30" a 15 minuti (costa poco averlo implementato)
Piuttosto mi pare esatto il suggerimento (non ricordo di chi) di usare file binari. In tal modo i 19 byte si sono ridotti ad 8.

B4X:
Dim raf As RandomAccessFile
    raf.Initialize(File.DirRootExternal, "provadat.dat", False)
    raf.WriteFloat(fLat,raf.CurrentPosition)
    raf.WriteFloat(fLon,raf.CurrentPosition)
    raf.Close
Le modifiche al mio progetto sono importanti. Soprattutto devo capire se il file provadat.dat passa per l'HTTP e poi devo leggere (codice ASP Classic) questo file.
Ho il mio bel da fare.
 

udg

Expert
Licensed User
Longtime User
non sono tonnellate di dati ma solo chili

avevo esagerato un pochino..eheh

Comunque in una mia app che fa qualcosa di simile (fondamentalmente sapere dove sia mio figlio senza dover chiamare e "rompere") acquisivo ogni 30minuti ma scartavo le letture identiche all'ultima perché mi indicavano che era fermo nell'ultima posizione (o nei paraggi) e mi tornava utile di notte se lasciava il cell acceso ed evitavo di registrare la stessa posizione più volte. Consumo batteria < 1mah.

ps: la mia app ha una funzione di privacy dove l'utente può disabilitare e riabilitare il tracciamento quando vuole.. (potrebbe anche spegnere il GPS, volendo).

pps: nel tuo caso, secondo me che non sono alpinista, un intervallo di 2 minuti come valore minimo della frequenza è più che sufficiente; magari anche 5..
 

Star-Dust

Expert
Licensed User
Longtime User
avevo esagerato un pochino..eheh

Comunque in una mia app che fa qualcosa di simile (fondamentalmente sapere dove sia mio figlio senza dover chiamare e "rompere") acquisivo ogni 30minuti ma scartavo le letture identiche all'ultima perché mi indicavano che era fermo nell'ultima posizione (o nei paraggi) e mi tornava utile di notte se lasciava il cell acceso ed evitavo di registrare la stessa posizione più volte. Consumo batteria < 1mah.

ps: la mia app ha una funzione di privacy dove l'utente può disabilitare e riabilitare il tracciamento quando vuole.. (potrebbe anche spegnere il GPS, volendo).

pps: nel tuo caso, secondo me che non sono alpinista, un intervallo di 2 minuti come valore minimo della frequenza è più che sufficiente; magari anche 5..
funziona anche con le fidanzate oltre che con i figli?
 
Last edited:

udg

Expert
Licensed User
Longtime User
Certo, ma in quel caso toglierei l'opzione privacy :D
 

AlpVir

Well-Known Member
Licensed User
Longtime User
Lasciando perdere considerazioni su figli e fidanzate (e perchè no le mogli ?) vorrei ritornare al punto, visto che nonostante l'esame accurato della libreria Random Access File (che consente di scrivere in binario), di B4XSerializator, di sub quali BytesToFileBytes e FileToBytes, di AsyncStreamObject e di altre cosucce non sono ancora riuscito ad ottenere quanto desiderato. O meglio, ci sarei riuscito in più di un modo ma l'output occupava sempre, in bytes, molto più dei files di testo fin qui utilizzati.
Quello che sembrava una semplice modifica del codice si rivela esso stesso un problema insormontabile, almeno per me.
Qualcuno ha già affontato tematiche simili o ha dei suggerimenti efficaci ?
Grazie per l'attenzione.
 

Star-Dust

Expert
Licensed User
Longtime User
Lasciando perdere considerazioni su figli e fidanzate (e perchè no le mogli ?) vorrei ritornare al punto, visto che nonostante l'esame accurato della libreria Random Access File (che consente di scrivere in binario), di B4XSerializator, di sub quali BytesToFileBytes e FileToBytes, di AsyncStreamObject e di altre cosucce non sono ancora riuscito ad ottenere quanto desiderato. O meglio, ci sarei riuscito in più di un modo ma l'output occupava sempre, in bytes, molto più dei files di testo fin qui utilizzati.
Quello che sembrava una semplice modifica del codice si rivela esso stesso un problema insormontabile, almeno per me.
Qualcuno ha già affontato tematiche simili o ha dei suggerimenti efficaci ?
Grazie per l'attenzione.
Per rimanere nel tema, come dissi su, non so se conviene per un risparmio del genere, visto che il codice potrebbe essere lungo e complicato?
Perché tu hai detto che vuoi stravolgere poco la tua App e non Passare a SQLite, e altri sistemi, visto che l'App già é funzionante.
Devi accettare un compromesso, o cambi il codice o ti tieni la lunghezza del file.

@@Star-Dust : nella mia ipotesi sono 2 byte su 19 se uso variabili double ma se uso delle float (ampiamente sufficienti per il mio caso) i byte risparmiati sono 10 su 19 (la metà !)
@@sirjo66 : ci sono altri dati fra cui la quota e il tempo. Il file deve necessariamente un txt, altrimenti non passa nel web attraverso il protocollo http.
Non risparmi la metà se oltre ai due float ci sono altri dati, ma al massimo risparmieresti il 24-25%

Premesso ciò. crea un nuovo tipo: Coordinate (float), Quota, Tempo.
I dati contenuto nel nuovo tipo li inserisci in una lista e li salvi in un file con File.WriteList. Cambia un pò il codice ma dovrebbe farti risparmiare. Oppure il classico SQL che io preferirei.
 

AlpVir

Well-Known Member
Licensed User
Longtime User
Dici bene "dovrebbe farti risparmiare". Ma non ne sono convinto visto che sempre file di testo si tratta. Il float "44.123456" in formato binario occupa 4 bytes ed in formato testo ne occupa 9 (senza contare il separatore, assolutamente necessario). Comunque proverò il WriteList.
Dai conti della serva che ho fatto il risparmio è sempre all'incirca di un fattore 1:2 (ossia la metà), per quanti dati (numerici) si inseriscano.
 

Star-Dust

Expert
Licensed User
Longtime User
Dici bene "dovrebbe farti risparmiare". Ma non ne sono convinto visto che sempre file di testo si tratta. Il float "44.123456" in formato binario occupa 4 bytes ed in formato testo ne occupa 9 (senza contare il separatore, assolutamente necessario). Comunque proverò il WriteList.
Dai conti della serva che ho fatto il risparmio è sempre all'incirca di un fattore 1:2 (ossia la metà), per quanti dati (numerici) si inseriscano.
Non so in B4A, Ma in Turbo Pascal se aprivi un type e lo salvavi non usava separatori. Perché avendo definito il Type la lunghezza di ogni elemento é di lunghezza fissa e stabilita, non devi separare come se fossero stringhe.

Prova
 

AlpVir

Well-Known Member
Licensed User
Longtime User
Prima della cura 42 bytes, dopo la cura 102 bytes.
Risultato ampiamente negativo !
Codice utilizzato :

B4X:
Process_Globals  Type Coordinate (Lat As Float, Lon As Float,Flag As Int , H As Int , Reg As Int, Inv As Int, Ora As Long )  
...
Dim lista As List
lista.Initialize
Dim CX As Coordinate
CX.Lat=Latitudine
CX.Lon=Longitudine
CX.Flag=0
CX.H=HI
CX.reg=0
CX.Inv=0
CX.Ora=Now
PTW.Write (strLog&Aggiunta)
lista.Add(CX)
PTW.WriteList (lista)
 

Star-Dust

Expert
Licensed User
Longtime User
Allora credo che già sei al minimo sindacabile.
 
Top