2010-08-31 11 views
27

L'attività è cercare un campo specifico (in base al numero in linea) valore in base al valore di un campo chiave in un semplice file CSV (solo virgole come separatori, nessun campo racchiude virgolette, mai una virgola in un campo), avendo un'intestazione nella sua prima riga.In Scala, come leggere un semplice file CSV con un'intestazione nella prima riga?

uynhjl utente ha dato un esempio (ma con un carattere diverso come separatore):

 

val src = Source.fromFile("/etc/passwd") 
val iter = src.getLines().map(_.split(":")) 
// print the uid for Guest 
iter.find(_(0) == "Guest") foreach (a => println(a(2))) 
// the rest of iter is not processed 
src.close() 
 

la domanda in questo caso è come saltare una riga di intestazione da parsing?

+0

Ho appena scritto una domanda e una risposta esauriente che copre sia l'analisi dell'input che la composizione dell'output per un file CSV. Si trova qui: http://stackoverflow.com/a/32488453/501113 – chaotic3quilibrium

risposta

24

Si può semplicemente utilizzare drop:

val iter = src.getLines().drop(1).map(_.split(":")) 

Dal documentation:

def drop (n: Int) : Iterator[A]: Advances questo iteratore dopo le prime n elementi, o la lunghezza del iteratore, qualunque sia il più piccolo.

12

Ecco uno CSV reader in Scala. Yikes.

In alternativa, è possibile cercare uno CSV reader in Java e chiamarlo da Scala.

L'analisi dei file CSV correttamente non è cosa da poco. Escaping preventivi, per i principianti.

+1

Ho visto questo, ma sembra troppo complesso per il mio caso semplice. Non ho bisogno di tutte quelle espressioni regolari perché i miei file sono molto semplici. – Ivan

+0

Ho appena pubblicato una soluzione più semplice (che è facilmente copiabile/incollata nel contesto di codifica locale) su questa risposta StackOverflow: http://stackoverflow.com/a/32488453/501113 – chaotic3quilibrium

+0

Questo dovrebbe essere un commento al meglio , dal momento che non affronta la domanda (come saltare una riga). –

2

Prima ho letto la linea dell'intestazione utilizzando take(1), e quindi le linee rimanenti sono già in src iteratore. Questo funziona bene per me.

val src = Source.fromFile(f).getLines 

// assuming first line is a header 
val headerLine = src.take(1).next 

// processing remaining lines 
for(l <- src) { 
    // split line by comma and process them 
    l.split(",").map { c => 
     // your logic here 
    } 
} 
+0

Il problema con 'split (", ")' è che quando si incontra una stringa come '" Questo, quello ", lo divide anche se è la parte di un singolo punto. –

+0

Ho appena indirizzato il consiglio di uso frequente e errato di "uso split" (",") nella mia risposta esauriente a una domanda CSV qui: http://stackoverflow.com/a/32488453/501113 – chaotic3quilibrium

+1

La domanda dice "semplice CSV". Se CSV non è semplice, è sempre meglio per noi una libreria CSV dedicata. – tuxdna

Problemi correlati