2012-01-11 16 views
7

Devo leggere un grande file di testo, diciamo, di 25 GB e devo elaborare questo file entro 15-20 minuti. Questo file avrà più sezioni di intestazione e piè di pagina.Lettura ed elaborazione di file di testo di 25 GB

Ho provato CSplit a dividere questo file in base all'intestazione, ma ci vogliono circa 24-25 minuti per dividerlo in un numero di file basato sull'intestazione, che non è affatto accettabile.

Ho provato lettura e scrittura sequenziale utilizzando BufferReader e BufferWiter insieme FileReader e FileWriter. Ci vogliono più di 27 minuti. Di nuovo, non è accettabile.

Ho provato un altro approccio come ottenere l'indice di inizio di ogni intestazione e quindi eseguire più thread per leggere il file da una posizione specifica utilizzando RandomAccessFile. Ma senza fortuna su questo.

Come posso raggiungere il mio requisito?

Possibile duplicato di:

Read large files in Java

risposta

7

provare a utilizzare un buffer di grandi dimensioni dimensione lettura (ad esempio, 20 MB invece di 2MB) al trattamento dei dati più veloce. Inoltre, non utilizzare BufferedReader a causa delle basse velocità e delle conversioni di caratteri.

Questa domanda è stato chiesto prima: Read large files in Java

0

Provare a utilizzare java.nio per utilizzare al meglio le funzionalità dei sistemi operativi. Evita di copiare i dati (ad esempio in una stringa), ma prova a utilizzare gli offset . Credo che le classi java.nio disporranno anche di metodi per trasferire dati da un buffer all'altro senza inserire i dati nello strato java (almeno su linux), ma questo si tradurrà essenzialmente nelle chiamate del sistema operativo.

Per molti server Web moderni questa tecnica è stata la chiave per le prestazioni con cui possono servire i dati statici: essenzialmente delegano il più possibile al sistema operativo per evitare di duplicarli nella memoria principale.

Vorrei sottolineare questo: la ricerca di un buffer di byte da 25 GB è molto più rapida della conversione in stringhe Java (che potrebbe richiedere codifica/decodifica del charset e copia). Tutto ciò che consente di risparmiare copie e gestione della memoria aiuterà.

+1

NIO ha i suoi brutti limiti progettati direttamente in esso: è possibile mappare 2 GB al massimo come buffer poiché l'API Buffer utilizza un int per tutti gli offset. Ciò rende Nio ingombrante nella migliore delle ipotesi per file di grandi dimensioni. – Durandal

5

È necessario assicurarsi che l'I/O sia sufficientemente veloce senza elaborazione perché sospetto l'elaborazione, non l'IO sta rallentando. Dovresti riuscire a ottenere 80 MB/s da un disco rigido e fino a 400 MB/s da un'unità SSD. Ciò significa che puoi leggere l'intero in un secondo.

Provare quanto segue, che non è il più veloce, ma il più semplice.

long start = System.nanoTime(); 
byte[] bytes = new byte[32*1024]; 
FileInputStream fis = new FileInputStream(fileName); 
int len; 
while((len = fis.read(bytes)) > 0); 
long time = System.nanoTime() - start; 
System.out.printf("Took %.3f seconds%n", time/1e9); 

A meno che non si trovi che si ottengono almeno 50 MB/s si ha un problema hardware.

0

Se la piattaforma è giusta, potresti voler sborsare e chiamare una combinazione di gatto e sed. Se non lo è, potresti comunque voler eseguire lo shell out e usare perl tramite la riga di comando. Per il caso che è assolutamente necessario che Java esegua l'elaborazione effettiva, gli altri hanno fornito risposte sufficienti.

Stare in guardia però, sborsare non è senza problemi. Ma perl o sed potrebbero essere gli unici strumenti ampiamente disponibili per eseguire la scansione e modificare 25 GB di testo nel tuo arco di tempo.

Problemi correlati