2011-11-24 11 views
5

Esiste un metodo per dividere un file di testo in java senza leggerlo?Divisione del file di testo senza leggerlo

Voglio elaborare un file di testo di grandi dimensioni in GB, quindi voglio dividere il file in piccole parti e applicare il filo su ogni file e combinare il risultato per esso.

Come leggerò per le parti più piccole, quindi dividere un file leggendolo non ha alcun senso dato che dovrò leggere lo stesso file per due volte e questo peggiorerà le mie prestazioni.

+0

proposto tag "file" –

risposta

2

Il tentativo di infilatura non è corretto. Se avete a che fare l'elaborazione significativa con i tuoi dati di file considera seguente struttura filettatura:

1 lettore Discussione (legge il file e alimenta i lavoratori)

  • coda con pezzi di lettura

1. .n Thread di lavoro (n dipende dai core della CPU, elabora i blocchi di dati dal thread del lettore)

  • Coda o dizionario con blocchi elaborati

1 thread di scrittura (Scrive risultati ad alcuni file)

Forse è possibile combinare il filo di lettura/scrittura in un thread, perché non ha molto senso per parallelizzare IO sullo stesso disco rigido fisico.

È chiaro che è necessario un po 'di sincronizzazione tra i thread. Soprattutto per le code pensare ai semafori

+0

ottimo suggerimento sicuramente proverò questo. – RamIndani

2

Senza leggere il contenuto del file non è possibile farlo. Non è possibile.

1

Qualcosa deve leggere il file per dividerlo (e probabilmente lo si vuole dividere in barriere di linea, probabilmente non in alcuni multipli di kilobyte).

Se si esegue su un computer Linux, è possibile delegare la suddivisione a un comando esterno come csplit. Quindi il tuo programma Java eseguirà semplicemente un comando csplit yourbigfile.txt.

+0

Il comando esterno leggerà il file e lo dividerà. Dov'è il vantaggio? –

+0

Evitare di farlo in Java. Forse più semplice da codificare (poiché l'utilità esiste già). Forse più veloce (ma non lo scommetterò). –

+0

scusa ho dimenticato di dire che sto lavorando su WindowsXP qualsiasi altro suggerimento sarebbe di grande aiuto. – RamIndani

2

non credo che questo è possibile per i seguenti motivi:

  1. Come si scrive un file senza "lettura" vero?
  2. Avrete bisogno di leggere nel testo per sapere dove è un limite di carattere (la codifica non è necessariamente 1 byte). Ciò significa che non è possibile trattare il file come binario.

Non è davvero possibile leggere riga per riga e elaborarlo in quel modo? Ciò consente anche di risparmiare spazio aggiuntivo che i file divisi occuperanno insieme all'originale. Per voi riferimento, la lettura di un file di testo è semplicemente:

public static void loadFileFromInputStream(InputStream in) throws IOException { 
    BufferedReader inputStream = new BufferedReader(new InputStreamReader(in)); 

    String record = inputStream.readLine(); 
    while (record != null) { 
    // do something with the record 
    // ... 
    record = inputStream.readLine(); 
    } 
} 

Stai solo leggendo una riga alla volta ... quindi la dimensione del file non influisce sulle prestazioni a tutti. Puoi anche fermarti ogni volta che devi. Se sei avventuroso puoi anche aggiungere le linee per separare i thread per accelerare l'elaborazione. In questo modo, IO può continuare a sfornare mentre elabori i tuoi dati.

Buona fortuna! Se, per qualche ragione, trovi una soluzione, per favore pubblica qui. Grazie!

+0

l'ho implementato usando il metodo linea per linea in BufferedReader ma sto cercando di ottenere migliori prestazioni con una migliore velocità di esecuzione. – RamIndani

2

Tecnicamente parlando - non può essere fatto senza leggere il file. Ma non è necessario mantenere l'intero contenuto del file in memoria per eseguire la divisione. Basta aprire un flusso sul file e scrivere su altri file reindirizzando l'output su un altro file dopo che un certo numero di byte è stato scritto su un file. In questo modo non è necessario conservare più di un byte di dati di file in memoria in un dato momento. Ma avendo un buffer più grande, circa 8 o 16kb aumenterà notevolmente le prestazioni.

1

In senso letterale n. Per dividere letteralmente un file in file più piccoli, devi leggere quello grande e scrivere quelli più piccoli.

Tuttavia, penso che tu voglia veramente sapere se puoi avere thread diversi che leggono in modo sequenziale "parti" diverse di un file allo stesso tempo. E la risposta è che puoi farlo. Basta che ogni thread crei il proprio oggetto RandomAccessFile per il file, seek nel punto pertinente e inizi a leggere.

(A FileInputStream probabilmente funzionerebbe troppo, anche se non credo che l'API specifiche Java garanzie che skip è implementato utilizzando un livello di sistema operativo "cercare" operazione sul file.)

Ci sono un paio di possibili complicazioni:

  • Se il file è di testo, è presumibilmente vuole ogni thread per avviare l'elaborazione all'inizio di qualche riga nel file. Quindi ogni thread deve iniziare trovando la fine di una riga e assicurarsi che legga fino alla fine dell'ultima riga nella sua "parte".

  • Se il file utilizza una codifica di caratteri a larghezza variabile (ad esempio UTF-8), è necessario occuparsi del caso in cui i limiti della partizione cadono nel mezzo di un carattere.

+0

Stavo pensando a un RandomAccessFile, ma come risolvi il problema con i limiti dei caratteri per schemi di codifica senza byte? cioè UTF-16, ecc. –

+1

@JacoVanNiekerk - con una programmazione attenta alla codifica. Ad esempio, con UTF-16 e UTF-8, lo schema di codifica garantisce che è possibile risincronizzare un limite di caratteri (reale) in un piccolo numero di byte. –

+0

RandomAccessFile sembra essere buono ma suppongo che funzioni su byte, che è una tecnica di lettura più lenta rispetto alla lettura della linea. Perfavore, correggimi se sbaglio. – RamIndani

Problemi correlati