Import "intelligente" di dati (CSV)

28 views
Skip to first unread message

Emmanuele Sordini

unread,
Jun 19, 2014, 4:49:13 AM6/19/14
to JUG Genova
Buongiorno a tutti,
mi rendo conto che il titolo della mia mail è un po' troppo generico, ma non ne ho saputo trovare uno migliore :-)

Cerco di spiegarmi brevemente. In un programma Java (applicazione web) devo importare dati da dei file CSV ad un database. La procedura prevede che l'utente dell'applicazione specifichi il tipo di dato (stringhe, numeri interi, numeri decimali, ecc.), in modo analogo a quanto avviene con l'import wizard di Excel.

La fase di identificazione dei dati funziona abbastanza bene, ed è cruciale perché influenza la creazione del database e quindi come saranno manipolati i dati, ma in effetti può essere assai tediosa per l'utente. Quindi mi (e vi) domando:

sapete per caso se esistano nelle librerie in Java (meglio se gratuite) in grado di effettuare una certa inferenza sui tipi di dati delle varie colonne analizzando il contenuto del file, in modo tale da permettermi di aiutare l'utente nel suo compito?

Grazie in anticipo a tutti!
Emmanuele

Andrea Rodriguez

unread,
Jun 19, 2014, 5:31:23 AM6/19/14
to jug-g...@googlegroups.com
ciao,
ho usato recentemente questa: http://supercsv.sourceforge.net/

...non so se é proprio quello che cerchi, ma l'ho trovata piuttosto efficace ed espandibile (usa il concetto della catena di processori x ogni colonna del file CSV...)

saluti
Andrea



--
Hai ricevuto questo messaggio perché sei iscritto al gruppo "jug-genova" di Google Gruppi.
Per annullare l'iscrizione a questo gruppo e non ricevere più le sue email, invia un'email a jug-genova+...@googlegroups.com.
Per postare in questo gruppo, invia un'email a jug-g...@googlegroups.com.
Visita questo gruppo all'indirizzo http://groups.google.com/group/jug-genova.
Per altre opzioni visita https://groups.google.com/d/optout.

Corrado Alesso

unread,
Jun 19, 2014, 5:44:26 AM6/19/14
to jug-g...@googlegroups.com
Ciao Emma, intanto se si tratta di CSV in Java, dai un'occhiata alla libreria SuperCSV che in passato mi ha risolto tanti grattacapi... in particolare pero' non so se ha la funzionalita' da te richiesta (so che ha i CellProcessor ma servono piu' per applicare vincoli ai dati, tra cui il tipo di dato, che pero' ovviamente deve essere conosciuto a priori).

Riguardo al tuo problema, mi pare che hai gia' elencato quasi tutte le varie possibilita', ovvero stringhe, numeri interi, numeri decimali. Mi vegono in mente ancora le date, ed eventualmente i valori booleani. In questo caso non si risolve facilmente con una cascata di Integer.parseInt, Double.parseDouble etc etc fino a String, e vedere il primo che non fallisce? Ok, per le date o scegli un formato prestabilito o potrebbe diventare rognoso.. Altrimenti non mi vengono in mente tool che facciano al caso tuo


--

Emmanuele Sordini

unread,
Jun 19, 2014, 6:19:01 AM6/19/14
to JUG Genova
Cari Corrado e Andrea,
grazie per la risposta, alla quale a mia volta rispondo cumulativamente.

Innanzitutto, io uso già SuperCSV nella mia applicazione, e mi trovo assai bene. Non avevo pensato alla cascata di processori, ci guarderò, anche se questo mi sembra che permetta solo di risolvere parzialmente il problema.

In particolare le date sono assai rognose (che cosa ne so di che formato avranno le date nel mio file? Ce ne sono potenzialmente tantissimi tipi!!), e anche tra numeri e stringhe bisogna stare attenti. Ad esempio, come fare a capire che un numero con zeri del tipo "004567" non è un vero e proprio numero, o meglio intrinsecamente lo è ma è un codice numerico e pertanto va trattato come stringa e non come numero? E potrei continuare...

Qualcuno invero mi ha parlato di strumenti che si chiamano ETL (http://en.wikipedia.org/wiki/Extract,_transform,_load), tipo CloverETL, Pentaho Kettle, etc che sono fatti apposta per manipolare grandi quantità di dati in I/O da e verso molte sorgenti eterogenee (file, database, etc). Però è un universo che non conosco, e comunque mi sembra che anche con questi strumenti l'apporto dell'utente nel discriminare i dati sia comunque necessario.

Voi ne sapete niente di questi strumenti?

Emmanuele

Andrea Rodriguez

unread,
Jun 19, 2014, 6:49:23 AM6/19/14
to jug-g...@googlegroups.com
Dalla tua risposta ho capito qualcosa di più ;-) 

mi sembra comunque una cosa non facile da "automatizzare" perché più legata alla fonte (umana) del dato che vai a leggere dal file CSV, più che alla tecnologia che puoi usare per tradurlo

ti servirebbero dei metadati descrittivi del formato, tipo le varie proposte di standard per i metadati degli open-data: ad es. ho trovato questi, che non conoscevo


in pratica si tratta di avere un descrittore JSON per il formato/contenuto dei dati testuali...

non credo che esista al momento qualche pacchetto Office che generi una simile accoppiata (dati + metadati) durante l'export in formato CSV, per cui potresti forse pensare ad un wizard intelligente che ad ogni import guidato del CSV ne salva il formato metadati scelto (dall'operatore durante lo stesso processo di import), e la volta successiva prova ad applicarlo al nuovo contenuto, proponendo all'operatore una o più scelte che "matchano" con il formato letto... la butto lì :-)

ciao
Andrea




Emmanuele Sordini

unread,
Jun 19, 2014, 7:50:36 AM6/19/14
to JUG Genova
2014-06-19 12:49 GMT+02:00 Andrea Rodriguez <rod...@gmail.com>:

mi sembra comunque una cosa non facile da "automatizzare" perché più legata alla fonte (umana) del dato che vai a leggere dal file CSV, più che alla tecnologia che puoi usare per tradurlo

Anche secondo me. Infatti la mia applicazione web al momento ha un import wizard tipo Excel, in cui viene mostrata un'anteprima del file in formato tabellare, e per ogni colonna una combo box in cui l'utente deve specificare il formato della colonna. A me sembra piuttosto facile ed intuitivo, ma mi è stato detto che anche così è comunque troppo complicato e che devo per forza fare in modo che sia l'applicazione a fare la maggior parte del lavoro di riconoscimento dei formati delle colonne.

La qual cosa a me sembra quasi impossibile da realizzare. Infatti la richiesta mi è stata rivolta da un manager, e che mi piaccia o no comanda lui :-(
 

ti servirebbero dei metadati descrittivi del formato, tipo le varie proposte di standard per i metadati degli open-data: ad es. ho trovato questi, che non conoscevo

Purtroppo l'approccio con i metadati è da scartare, poiché non posso aspettarmi che siano a disposizione.

Lo scenario di utilizzo tipo infatti prevede che sia l'utente a importare online un file CSV che potrebbe aver estratto od ottenuto in chissà quale modo. Si può certamente chiedere che il file rispetti alcuni requisiti minimi di formato e di qualità, ma non che siano disponibili i metadati, dato che il più delle volte si tratta di utenti che dell'informatica sono solo utilizzatori, ma non tecnici.

Emmanuele

Alessio Stalla

unread,
Jun 19, 2014, 8:02:24 AM6/19/14
to jug-g...@googlegroups.com
Potresti comunque fare una serie di parse (int, double, Date in vari formati) per decidere empiricamente un tipo di dato ma lasciare sempre la possibilità di scelta all'utente?


--

Emmanuele Sordini

unread,
Jun 19, 2014, 9:39:45 AM6/19/14
to JUG Genova
2014-06-19 14:01 GMT+02:00 Alessio Stalla <alessi...@gmail.com>:
Potresti comunque fare una serie di parse (int, double, Date in vari formati) per decidere empiricamente un tipo di dato ma lasciare sempre la possibilità di scelta all'utente?

Sì, certo, quello senz'altro si può fare, e pertanto ci proverò. Ho però la sensazione che non sia "abbastanza automatico" per il capo e che quindi non sia così facile da "far digerire".

Emmanuele

Stefano Gamma

unread,
Jun 19, 2014, 10:27:53 AM6/19/14
to jug-g...@googlegroups.com
Ciao,
provo a dare il mio piccolo contributo
Se non ho capito l'obbiettivo da raggiungere è preso in input un file CSV ne leggo qualche riga a campione per capire la tipologia del dato per così da fornire all'utente una maschera del tipo

Campo 01 : Stringa
Campo 02 : Data
Campo 03 : intero
Campo 04 : intero decimale

dove l'utente può interagire per apportare eventuali modifiche se l'algoritmo ha sbagliato qualcosa, dopodichè dare il via all'import effettivo del file.

Forse banalizzo, ma non potresti mettere insieme una serie di regular expression per capire di quale tipologia di dato si tratta?


Ciao


Emmanuele Sordini

unread,
Jun 20, 2014, 4:26:02 AM6/20/14
to JUG Genova
2014-06-19 16:27 GMT+02:00 Stefano Gamma <stefan...@gmail.com>:

Se non ho capito l'obbiettivo da raggiungere è preso in input un file CSV ne leggo qualche riga a campione per capire la tipologia del dato per così da fornire all'utente una maschera del tipo

Campo 01 : Stringa
Campo 02 : Data
Campo 03 : intero
Campo 04 : intero decimale

dove l'utente può interagire per apportare eventuali modifiche se l'algoritmo ha sbagliato qualcosa, dopodichè dare il via all'import effettivo del file.


Esatto, hai capito bene, ed è così che già funziona la mia GUI. Però la preview è data in forma tabellare verticale, e se il file CSV ha diciamo più di sei o sette colonne, esse non ci stanno tutte nella finestra e quindi l'utente deve scorrere verso destra la barra per accedere alle combo box per la scelta del tipo dei campi. Quindi un miglioramente potrebbe già essere quello di far vedere i campi della tabella su più righe, proprio come hai scritto tu sopra.

 
Forse banalizzo, ma non potresti mettere insieme una serie di regular expression per capire di quale tipologia di dato si tratta?


Ci ho pensato, ma - sono sincero, non c'è niente di cui vergognarsi - le regular expression sono una cosa astrusa che non sono mai riuscito veramente a padroneggiare, perciò preferisco starne alla larga se non per compiti estremamente semplici e limitati. Definizione che non si applica al problema in questione. Perciò l'alternativa forse più manutenibile è quella di una catena di parser magari scelta in modo un po' furbo, anche facendo alcune ragionevoli ipotesi sul tipo di dato.

Emmanuele

Stefano Gamma

unread,
Jun 20, 2014, 5:18:14 AM6/20/14
to jug-g...@googlegroups.com
Come vuoi, ma secondo me te la vai a cercare e rischi di infilarti in un vespaio.
Se cerchi un pò in giro le trovi già fatte le regular per verificare date, formati numerici, etc etc.

Buon lavoro!!!



--

Alessio Stalla

unread,
Jun 20, 2014, 5:28:45 AM6/20/14
to jug-g...@googlegroups.com
Non sono d'accordo, io preferirei la soluzione con i parser, per il seguente motivo: comunque per essere inseriti nel DB con il tipo corretto i dati andranno parserizzati; a questo punto tanto vale usare il parser anche come validatore del formato del dato. Altrimenti si rischiano situazioni in cui la regexp dice "pippo" ma parsePippo fallisce. L'unico motivo che vedrei eventualmente per preferire le regexp sono considerazioni di performance, ma naturalmente senza fare misurazioni non si può dire niente.

Stefano Baghino

unread,
Jun 20, 2014, 6:05:28 AM6/20/14
to jug-g...@googlegroups.com
[OT] Ma come, non vuoi diventare un eroe con le regex? https://xkcd.com/208/


--
Hai ricevuto questo messaggio perché sei iscritto al gruppo "jug-genova" di Google Gruppi.
Per annullare l'iscrizione a questo gruppo e non ricevere più le sue email, invia un'email a jug-genova+...@googlegroups.com.
Per postare in questo gruppo, invia un'email a jug-g...@googlegroups.com.
Visita questo gruppo all'indirizzo http://groups.google.com/group/jug-genova.
Per altre opzioni visita https://groups.google.com/d/optout.



--
Ste

Emmanuele Sordini

unread,
Jun 20, 2014, 8:02:41 AM6/20/14
to JUG Genova
2014-06-20 11:28 GMT+02:00 Alessio Stalla <alessi...@gmail.com>:
Non sono d'accordo, io preferirei la soluzione con i parser, per il seguente motivo: comunque per essere inseriti nel DB con il tipo corretto i dati andranno parserizzati; a questo punto tanto vale usare il parser anche come validatore del formato del dato. Altrimenti si rischiano situazioni in cui la regexp dice "pippo" ma parsePippo fallisce. L'unico motivo che vedrei eventualmente per preferire le regexp sono considerazioni di performance, ma naturalmente senza fare misurazioni non si può dire niente.

Le regular expression sono molto potenti, ma sono anche un'arma a doppio taglio se non le conosci bene, perché magari quelle preconfezionate non vanno bene così come sono e c'è bisogno di adattarle. Inoltre qui le performance non sono importanti, perché sia le regexp sia i parser mi servono solo per aiutare ad identificare il tipo di dato su un campione di qualche decina o al massimo di qualche centinaio di dati presi in modo assolutamente casuale; una volta creata la tabella, l'import dal file CSV al dabatase verrebbe comunque demandato ad una qualche routine di bulk import, senza effettuare nessuna elaborazione sui singoli campi dei singoli record.

E comunque ci sono dei casi (e non pochi) dove né loro, né i parser sono la soluzione adatta. Prendi ad esempio due casi che so essere piuttosto comuni nei tipi di dati CSV che la mia applicazione tratta.

Il primo caso è costituito da stringhe solo numeriche di lunghezza omogenea, tipo "20056789", "45009988", ecc., non sono dei numeri ma sono dei codici, e come tale vanno trattati come stringhe e non come numeri, perché se hai la sfiga di avere un codice che inizia con degli zeri, tipo "00056345", se provi a convertirlo in intero ti perdi gli zeri iniziali e hai rovinato l'informazione.

Il secondo caso è sempre una serie di numeri interi, tipo "199801", "201005", ecc. i quali altro non sono che date senza il giorno, del tipo YYYYmm. Ora come cavolo fai a capire che si trattano di date, e non di semplici numeri, se non avendo informazioni collaterali riguardo alla natura del dato stesso? Io personalmente non riesco a immaginare che esista un sistema o un software per quanto intelligente che sia in grado di discriminare correttamente questo tipo di casi soltanto guardando i dati grezzi.

La verità è che in casi come questi il ruolo contributo dell'essere umano è *essenziale*. Al massimo, gli si può provare a dare un aiutino cercando di risolvere i casi più semplici.

Emmaneule

Alessio Stalla

unread,
Jun 20, 2014, 8:07:42 AM6/20/14
to jug-g...@googlegroups.com
Sì, certo. Comunque se hai tanti dati su cui fare inferenza puoi andare molto lontano mettendo il parser dei numeri a priorità molto bassa e preponendo parser specifici per i tipi che tratti, ad esempio uno che se trova stringhe che iniziano con "0" non le tratta come numeri, un SimpleDateFormat con pattern yyyyMM, ecc. anche se alla fin fine la possibilità di intervento umano rimane imprescindibile.


Reply all
Reply to author
Forward
0 new messages