Domanda

Sto usando C# e scrivo i miei dati in file CSV (per ulteriori utilizzo). Tuttavia i miei file sono cresciuti su larga scala e devo trasporli. Qual è il modo più semplice per farlo. in qualsiasi programma?

Gil

È stato utile?

Soluzione

In aumento di complessità (e anche aumentando l'ordine di capacità di gestire file di grandi dimensioni):

  • Leggi il tutto in un array 2-D (o array frastagliato aka array di array).
    • Memoria richiesta: uguale alla dimensione del file

  • Tracciare l'offset del file all'interno di ogni riga. Inizia trovando ciascuna nuova linea (non citata), memorizzando la posizione attuale in a List<Int64>. Quindi iterare in tutte le righe, per ogni riga: cercare la posizione salvata, copiare una cella sull'output, salvare la nuova posizione. Ripeti fino a quando non si esaurisce le colonne (tutte le righe raggiungono una nuova linea).
    • Memoria richiesta: otto byte per riga
    • Il file frequente cerca sparsi in un file molto più grande della cache del disco provoca un battito del disco e prestazioni miserabili, ma non si bloccherà.

  • Come sopra, ma lavorando su blocchi di file 8K. Ciò creerà un set di file ciascuno con colonne 8K. Il blocco di input e l'uscita si adattano tutti alla cache del disco, quindi non si verifica alcun thrashing. Dopo aver costruito i file a strisce, iterare attraverso le strisce, leggere una riga da ciascuna e aggiungere all'output. Ripeti per tutte le righe. Ciò si traduce in una scansione sequenziale su ciascun file, che ha anche un comportamento di cache molto ragionevole.
    • Memoria richiesta: 64K per il primo passaggio, (conteggio delle colonne/8K) Descrittori di file per il secondo passaggio.
    • Buone prestazioni per tabelle fino a diversi milioni in ogni dimensione. Per set di dati ancora più grandi, combina solo pochi (ad esempio 1K) dei file di strisce, facendo un set più piccolo di strisce più grandi, ripeti fino a quando non hai una sola striscia con tutti i dati in un file.

Commento finale: potresti spremere più prestazioni utilizzando C ++ (o qualsiasi lingua con supporto puntuale corretto), file mappati in memoria e puntatori invece di offset di file.

Altri suggerimenti

Dipende davvero. Li stai tirando fuori da un database? È possibile utilizzare una dichiarazione di importazione MySQL. http://dev.mysql.com/doc/refman/5.1/en/load-data.html

Oppure è possibile che tu possa utilizzare il ciclo tramite i dati aggiungendolo a un flusso di file utilizzando l'oggetto StreamWriter.

StreamWriter sw = new StreamWriter('pathtofile');
foreach(String[] value in lstValueList){
String something = value[1] + "," + value[2];
sw.WriteLine(something);
}

Ho scritto una piccola sceneggiatura di prova qui a Python. Ammetto che è un passeggino e probabilmente ci sono alcuni miglioramenti delle prestazioni da apportare, ma lo farà. L'ho eseguito contro un file 40x40 e ho ottenuto il risultato desiderato. Ho iniziato a eseguirlo contro qualcosa di più simile al tuo set di dati di esempio e mi ci è voluto troppo tempo per aspettare.

path = mkdtemp()
try :
    with open('/home/user/big-csv', 'rb') as instream:
        reader = csv.reader(instream)        
        for i, row in enumerate(reader):
            for j, field in enumerate(row):                
                with open(join(path, 'new row {0:0>2}'.format(j)), 'ab') as new_row_stream:
                    contents = [ '{0},'.format(field) ]
                    new_row_stream.writelines(contents)
            print 'read row {0:0>2}'.format(i)
    with open('/home/user/transpose-csv', 'wb') as outstream:
        files = glob(join(path, '*'))
        files.sort()
        for filename in files:
            with open(filename, 'rb') as row_file:
                contents = row_file.readlines()          
                outstream.writelines(contents + [ '\n' ]) 
finally:
    print "done"
    rmtree(path)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top