2013-06-06 22 views
6

Ho scritto il mio lettore/scrittore CSV in C per archiviare i record in una colonna di caratteri in un database ODBC. Sfortunatamente ho scoperto molti casi limite che inciampano sulla mia implementazione, e sono giunto alla conclusione che il mio problema è che non ho definito rigorosamente le regole per CSV. Ho letto RFC4180, ma sembra incompleto e non risolve le ambiguità.Definizione rigorosa per lettura/scrittura file CSV

Ad esempio, "" deve essere considerato un token vuoto o una virgola doppia? Le virgolette coincidono all'esterno o tra sinistra e destra? Cosa devo fare con una stringa di input che ha virgolette singole non abbinate? Il vero casino comincia quando ho dei token nidificati, che raddoppiano i caratteri di citazione evasi.

Quello di cui ho veramente bisogno è uno standard CSV definitivo che possa essere implementato nel codice. Ogni volta che sento di aver inchiodato ogni angolo, ne trovo un altro. Sono sicuro che questo problema è stato ripensato e risolto molte volte da menti superiori alle mie, qualcuno ha scritto una definizione rigorosa di CSV che posso implementare nel codice? Mi rendo conto che C non è la lingua ideale qui, ma non ho una scelta riguardo al compilatore in questa fase; né posso usare una libreria di terze parti (a meno che non compili con C-90). Boost non è un'opzione in quanto il mio compilatore non supporta C++. Ho pensato di abbandonare CSV per XML, ma sembra eccessivo per la memorizzazione di alcuni token in un record di 256 caratteri. Qualcuno ha fatto una specifica CSV definitiva?

+1

http://stackoverflow.com/questions/14115529/parse-csv-file-in-c La biblioteca ha suggerito qui è ANSI C89 compatibile. – Nobilis

risposta

0

Trova la libreria CSV più autorevole di cui ti fidi e leggi la fonte. CSV non è così complicato da non essere in grado di comprendere le sue regole da una lettura completa di un'implementazione sorgente. Sono stato contento di Java opencsv. Perl's è here e così via.

1

Non esiste uno standard (vedi l'articolo di Wikipedia, in particolare http://en.wikipedia.org/wiki/Comma-separated_values#Lack_of_a_standard), in modo da poter utilizzare CSV, è necessario seguire il principio generale di essere prudenti in quello di generare e liberale in ciò che accetti. In particolare:

  • Non utilizzare le virgolette per i campi vuoti. Basta scrivere un campo vuoto (due delimitatori adiacenti o un delimitatore nella prima/ultima posizione della linea).
  • Quota qualsiasi campo contenente virgolette, virgola o nuova riga.
+0

Sebbene la RFC non sia uno standard, è molto chiaro - non vedo confusione nel testo. L'articolo di Wikipedia che hai collegato parla di file CSV in termini laici - ad esempio, Excel raggruppa tutti i file basati su testo in CSV e quindi il wizard di importazione può essere utilizzato per selezionare il separatore, ecc. – xxbbcc

+0

Inoltre, non penso sia molto buon consiglio di avere regole diverse per quotare i valori del campo durante la scrittura di un file CSV. Se tutti i valori dei campi sono quotati, l'analisi del file è molto semplice. – xxbbcc

+0

@xxbbcc: Come osservato da OP, la citazione di campi vuoti non è "essere conservativi in ​​ciò che si genera" perché c'è un'ambiguità su come "" "è interpretato. Anche la RFC non è chiara a meno che non si ignori semplicemente il testo inglese della RFC e si segua la grammatica ABNF. –

0

Secondo RFC 4180, i campi devono essere analizzati da sinistra a destra per interpretare correttamente una virgoletta doppia. In alcuni contesti "" è un doppio apaping (quando si trova all'interno di un campo quotato), altrimenti è una stringa vuota o due virgolette doppie (quando si trova all'interno di un valore di campo altrimenti non vuoto).

Si consideri ad esempio un file con 4 record (1 colonna):

"field""value" CRLF 
"" CRLF 
field""value CRLF 
"field value" extra CRLF 
  1. "field""value" - dovrebbe essere letto come field"value
  2. "" - deve essere letto come una stringa vuota
  3. field""value - deve essere letto come field""value
  4. "field value" extra - può essere letto come field value extra oppure puoi rifiutarlo

Il record 4 è davvero un campo non valido, quindi puoi accettarlo o rifiutarlo.

Quando si inizia a leggere un campo, è necessario verificare se il primo carattere letto è una doppia citazione o meno. Se il primo carattere è una doppia citazione, il valore del campo è quotato e devi leggere finché non trovi una doppia virgoletta di chiusura senza caratteri di escape. In questo caso puoi ignorare le nuove righe e i caratteri virgola, dato che il campo è quotato, ma termina solo quando si incontra una doppia virgoletta di chiusura.

Se il primo carattere non è una virgoletta doppia, tutte le virgolette nel valore del campo devono essere trattate come doppi valori letterali. In questo caso si raggiunge la fine del campo quando si incontra una virgola o un nuovo carattere di linea.

In base a ciò, mi consiglia di citare sempre tutti i campi quando si scrivono i record e si scrive un parser appropriato per analizzare i record durante la lettura dei dati. In questo modo è possibile memorizzare tutti i dati nei file CSV (anche testo multilinea con citazioni incorporate) e il formato sarà chiaro. Durante la lettura di un file CSV, fallirei tutti i file che non possono essere analizzati correttamente - se si tratta di un database, è possibile aspettarsi che gli utenti non facciano casini con i record manualmente, a meno che non sappiano cosa stanno facendo.