Il modo migliore per gestire i file delimitati


16

Quindi in genere un file CSV utilizza una virgola e il carattere restituito come delimitatori di campo e di riga.

Ciò si traduce in ovvi problemi con il testo che può contenere entrambi questi caratteri.

Ovviamente ci sono opzioni lì (scappandole) ma come fanno le persone a gestirlo? Usa personaggi diversi - pipe o tildas? Sfuggirli? Non usare file delimitati, dopo tutto è il 2010 e ora abbiamo XML?

Guardando almeno lo sforzo per una discreta possibilità di non vedere problemi.

(Giusto per essere chiari, questa è una domanda per curiosità piuttosto che per qualcosa di più solido - è qualcosa che mi sono imbattuto di volta in volta giocando con i dati, ci ho sempre aggirato ma normalmente sembra un po ', beh, sporco, e mi chiedevo quale fosse l'esperienza degli altri).


Pensa attentamente all'utilizzo di CSV: è bello e facile da gestire (vedi le risposte per le regole di fuga comuni), ma non è quasi interoperabile come dovrebbe essere - se stai solo comunicando con i tuoi programmi va bene, ma se tu voler importare altrove diventa un po 'strano perché programmi diversi obbediscono a diverse regole di escape.
Michael Kohne,

@Michael - Assolutamente. Il problema però è che è così onnipresente che quasi sempre ti vengono in mente momenti in cui è un'opzione molto allettante, e nel caso di molti sistemi più vecchi è l'unica opzione.
Jon Hopkins,

Esistono librerie mature in molte lingue (certamente quelle comuni) per leggere e scrivere file delimitati da caratteri. Gestiranno quasi ogni situazione. Scrivere il proprio parser CSV sembra essere un tipo comune di anti-pattern.
Quentin-starin,

Risposte:


13

Secondo Wikipedia :

I campi con virgole incorporate devono essere racchiusi tra virgolette doppie.

E inoltre:

I campi con caratteri di virgolette doppie devono essere racchiusi tra caratteri di virgolette doppie e ciascuno dei caratteri di virgolette doppie incorporate deve essere rappresentato da una coppia di caratteri di virgolette doppie.

Non so chi l'abbia inventato, ma dimostra che alla fine devi fuggire. È l'unica soluzione solida. Tutto il resto è solo un nastro adesivo sopra il nastro adesivo: forse funziona per ora, ma alla fine ti imbatterai in un caso in cui hai bisogno di un'eccezione a eccezione di un'eccezione, e non ci vuole molto tempo prima che il tuo groviglio di regole è molto più complesso di quanto non fosse stata una semplice soluzione di carattere di fuga.

Sembra che i creatori di CSV abbiano prima tentato di evitare le virgole sfuggendo presentando una sintassi speciale tra virgolette doppie, che consentiva di salvare le virgole, ma poi qualcuno voleva salvare anche i caratteri con virgolette doppie, quindi hanno dovuto scappare a quel punto - usando stranamente il virgoletta doppia come personaggio di escape. Se avessero deciso di fuggire correttamente in primo luogo, la sintassi sarebbe ora più semplice.


3
Cosa dovrebbe essere e ciò che è .. spesso differisce :)
Tim Post

Penso che la soluzione sia abbastanza ok. Per dati semplici, CSV funziona benissimo, per dati complessi è quindi necessario un preventivo e la fuga "con" "torna a BASIC.
Ernelli,

1
@Ernelli: ora che ci penso di più, potrebbe effettivamente essere un ragionevole compromesso tra leggibilità umana e semplicità. Il problema che sfugge è che sembra brutto per gli umani , anche se è banale che il computer analizzi. Pertanto, riservando le fughe solo per rari casi ("campi con caratteri di virgolette doppie incorporate") si produce un output che di solito sembra abbastanza leggibile dall'uomo. Questa è una buona soluzione, supponendo che le virgole nei nomi dei campi vengano utilizzate più frequentemente rispetto alle virgolette doppie nei nomi dei campi.
Joonas Pulakka,

2

Suppongo che tu abbia qualcosa del genere:

Foo,Baz,,,"Foo,Baz"

Se le stringhe che contengono il delimitatore non vengono quotate o salvate, non esiste un modo realmente affidabile per analizzare il file.

Puoi, tuttavia, esaminare i dati per analizzare e trarre conclusioni come:

  • I float separati da virgola devono essere trattati come una stringa
  • Se la riga precedente o successiva contiene meno delimitatori, saltare l'analisi di questa riga e registrarla
  • Tratta "come"

Devi scrivere un parser per gestire cose del genere, ma non deve essere complicato.

Nella mia esperienza, l'importazione di discariche di massa da qualcosa come Excel comporta sempre la necessità di tornare indietro e rivedere alcune stranezze. La sfida è di dare il vostro programma appena abbastanza buon senso per quanto riguarda i dati in modo che non fa un inserto folle. Quindi rivedere ciò che è stato registrato e lavare / risciacquare / ripetere.

Una volta ho gestito una FAQ interna per una piccola azienda che utilizzava tutte le workstation Ubuntu. Una parte delle FAQ ha dato "scorciatoie da shell", e mi è venuto delimitato da pipe. Bene, le risposte erano anche tipicamente delimitate da pipe (cioè grep foo | qualcosa) e non citate o sfuggite. Sento quel dolore :)


2

Niente di sbagliato con CSV fino a un certo punto

CSV funziona bene per dati rigidamente definiti che è improbabile che cambino formato e che non generino molte sorprese sul parser del destinatario.

Ecco un utile elenco dei grandi gotcha:

  1. Esc "" s entro "" s (il campo contiene delimitatore di campo)
  2. "" s contenenti CRLF (il campo contiene delimitatore di riga)
  3. Unicode (il formato di testo sottostante potrebbe essere insufficiente)
  4. Terminatori di linea diversi per sistemi operativi diversi (è CR o CRLF o LF o NUL?)
  5. Commenti incorporati (riga preceduta da #, //, -,; ecc.)
  6. Gestione della versione (l'ultima versione del file contiene più o meno campi)
  7. Differenziazione tra NULL e dati vuoti (, "", è vuoto ma ,, è nullo?)

Puoi affrontarlo con un'intestazione di metadati che descrive come analizzare i campi, ma puoi anche usare XML. È a causa di questo tipo di pasticcio CSV a forma libera che è stato inventato. L'approccio XML sembra troppo pesante per quello che potrebbe, a prima vista, essere un problema semplice.

Un'alternativa popolare è la strategia "delimitatore di caratteri strani". Questo aggira molti dei problemi di fuga sopra perché usi qualcosa come un | carattere (pipe) per la delimitazione dei campi e un CRLF per la terminazione dei record. Questo non aggira il problema del campo multilinea (a meno che tu non usi un contatore di campi) ma ottieni linee ben formattate per gli umani.

Nel complesso, se stai solo cercando un modo semplice per gestire questo tipo di file, nel mondo Java, potresti semplicemente lanciare OpenCSV . In questo modo si astraggono tutti i problemi in un quadro consolidato.


2

CSV è ancora un formato valido in molte situazioni, soprattutto perché deve essere ancora il modo più semplice per un cliente di scrivere dati che devono essere importati nella tua applicazione. Pochi dei nostri clienti amano avere a che fare con XML, forse perché è molto dettagliato e ha tutte quelle parentesi angolari "spaventose". È molto più semplice per loro avvolgere il cervello attorno a un semplice elenco di elementi separati da un personaggio concordato e anche concordare che lo stesso personaggio non sarà consentito nel contenuto di un campo.

Detto questo, devi ancora gestire correttamente l'input e verificare le situazioni in cui usano caratteri non validi. Ho iniziato a utilizzare FileHelpers per le mie esigenze di analisi CSV.


1

di solito mi attengo allo standard e sfuggirli. nella maggior parte dei linguaggi di programmazione è disponibile un buon supporto integrato o una buona libreria.

dipende dalla situazione in quale formato verrà utilizzato e CSV è un formato ragionevole per lo scambio di strutture di formati di dati semplici.


0

Dimentica CSV, usa JSON . Facile da scrivere, facile da analizzare. XML è così 2005 .


6
e ha lo stesso problema quando si desidera utilizzare un personaggio che fa parte del formato JSON (come {o,)
Salandur

Salandur: Niente affatto! Ci sono regole esatte su come fuggire! Ma {e, non c'è nemmeno bisogno di essere sfuggiti, perché dentro sono stringhe, non sono ambigue!
user281377

1
Bene e bene, ma non ricordo che Excel abbia una funzione "Esporta in JSON" :) Ci sono momenti in cui devi analizzare cose strane, se non altro per metterle in un formato più gradevole.
Tim Post

1
E JSON è semplicemente così geniale per aver passato circa un milione di oggetti della stessa forma. Oh aspetta.
Frank Shearar,

1
JSON non offre alcun miglioramento rispetto a CSV in merito a questa domanda e manca in modo determinante l'interoperabilità con molte applicazioni (come è stato menzionato, non è possibile importare o esportare da Office, DB SQL ecc.). JSON è ottimo per operazioni interne e leggere sul lato client, ma XML è molto meglio per il passaggio di dati tra applicazioni.
Dan Diplo,

0

Di solito, quello che mi ritrovo a fare è ottenere un TSV (valori separati da tabulazioni) piuttosto che un file CSV, estrarre il file in Emacs e vedere quale dei pochi caratteri insoliti non utilizza MAI ($ è di solito una buona scelta qui), e poi converto tutte le schede in $.

Da lì, si può dire a GNU AWK di usare $ come separatore di campo e Bob è tuo zio.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.