2011-01-27 21 views
6

Ho un file CSV da 10 GB che è essenzialmente un'enorme matrice quadrata. Sto cercando di scrivere una funzione in grado di accedere a una singola cella della matrice nel modo più efficiente possibile, cioè la matrice [12345,20000].accesso casuale CSV; C#

Data la sua dimensione, non è ovviamente possibile caricare l'intera matrice in un array 2D, ho bisogno di leggere in qualche modo i valori direttamente dal file.

Ho cercato su Google l'accesso casuale ai file utilizzando FileStream.Seek, ma sfortunatamente a causa dell'arrotondamento variabile ogni cella non ha una larghezza fissa. Non sarebbe possibile per me cercare un byte specifico e sapere quale cella sto guardando con una sorta di aritmetica.

Ho considerato la scansione del file e la creazione di una tabella di ricerca per l'indice del primo byte di ogni riga. In questo modo, se volessi accedere alla matrice [12345,20000], cercherò di ricorrere all'inizio della riga 12345 e quindi eseguirò la scansione attraverso la linea, contando le virgole fino a quando raggiungo la cella corretta.

Sto per provarlo, ma qualcun altro ha qualche idea migliore? Sono sicuro che non sarei la prima persona a cercare di trattare un file come questo.

Acclamazioni

Edit: Vorrei sottolineare che il file contiene una matrice molto sparsa. Se l'analisi del file CSV dovesse risultare troppo lenta, prenderei in considerazione la possibilità di convertire il file in un formato di file più appropriato e più facile da elaborare. Qual è il modo migliore per memorizzare una matrice sparsa?

risposta

3

Ho utilizzato il lettore CSV Lumenworks per file CSV di grandi dimensioni, potrebbe valere la pena dare un'occhiata veloce per vedere quanto velocemente può analizzare il file.

Lumenworks CSV

+1

Non vedo come questo possa impedire sia la ricerca che il caricamento di tutti in RAM. È solo un lettore sequenziale. –

1

index-file sarebbe la migliore che si possa fare. Scommetto. Con una dimensione della riga sconosciuta, non è possibile saltare direttamente alla riga se non eseguendo la scansione del file o un indice.

L'unica domanda è quanto è grande il tuo indice. Se è troppo grande, è possibile ridurlo indicizzandone solo ogni 5 (ad esempio) e scansioni in un intervallo di 5 righe.

3

Prima di tutto, come vorresti fare riferimento a una particolare riga? È l'indice della riga in modo che tu abbia un'altra tabella o qualcosa che ti aiuti a sapere quale riga ti interessa? o è un ID o qualcosa?

Queste idee vengono in mente

  • Il tuo approccio
  • di ricerca binaria. Supponendo che tu abbia una lunghezza media (dimensione/righe), puoi usare una ricerca binaria per trovare una riga assumendo che ci sia un identificatore nella riga ordinata e in grado di dirti se sei o meno.
  • Caricarlo in un database! A proposito, cosa ti impedisce di farlo? È anche possibile utilizzare SQL Express - che è gratuito - e per aggirare il limite di dimensioni, è possibile shard i dati su più database.
+0

* Caricamento in un database * ... che creerebbe un indice su quello :) –

+0

Mi piace l'idea della ricerca binaria. Tuttavia, come hai affermato, gli richiederebbe un rowid su ogni riga di csv. –

+0

Stranamente la matrice è stata generata da dati da un database SQL. Non ho creato il generatore e ora devo occuparmi dell'output. Sto considerando di riportare i dati in un datatype più strutturato. Dovrei usare MSSQL o un file binario? – user593062

0

Non sono d'accordo sul fatto che non si debba caricare il file nella RAM, soprattutto se si utilizza un sistema operativo a 64 bit.

Non dovrebbe essere un problema allocare una matrice di dimensioni 12345x20000: è solo circa 1.9 GB in doppia precisione. E infatti, anche se la dimensione fosse più grande, raccomanderei comunque questo approccio sotto una piattaforma a 64 bit (vedi "memoria virtuale").

In secondo luogo hai dichiarato che la tua matrice era sparsa, quindi potresti caricare nella RAM ma usare una rappresentazione sparsa per risparmiare un po 'di memoria.

In conclusione se la tua applicazione richiede molti accessi alla tua matrice e le prestazioni sono un po 'importanti, metterlo nella RAM sarebbe sicuramente il mio approccio preferito.

+0

Ovviamente, è possibile eseguire tale elaborazione e inserire il risultato in un file piuttosto che in RAM, si otterrebbe comunque una ricerca a tempo costante, ma sarebbe più lenta – Greg

0

Pre-elaborare il file in modo che i campi siano a larghezza fissa. Quindi puoi fare facilmente la tua lettura casuale.

In questo modo è possibile scrivere un codice semplice che legge il file di larghezza variabile 10G da un disco locale e scrive un file di larghezza fissa 10G su un disco locale in pochi (~ 20). minuti. Se questo investimento iniziale è redditizio dipende dal numero di letture casuali che devi fare e dalla frequenza con cui il file da leggere cambia.

0

Cosa succede se si crea un file separato 12345 che viene letto con l'istanza Lazy. Ogni file verrebbe letto solo se i dati fossero necessari. Se i dati sono completamente sparsi, è possibile creare una struttura dati con una proprietà bool IsEmpty.

Hai bisogno di accedere allo stesso elemento più volte o hai bisogno di leggere solo ogni elemento una volta?