Il modo più veloce per scrivere su file?

Ho creato un metodo che accetta un File e una String . Sostituisce il file con un nuovo file con quella stringa come suo contenuto.

Questo è quello che ho fatto:

 public static void Save(File file, String textToSave) { file.delete(); try { BufferedWriter out = new BufferedWriter(new FileWriter(file)); out.write(textToSave); out.close(); } catch (IOException e) { } } 

Tuttavia è dolorosamente lento. A volte ci vuole più di un minuto.

Come posso scrivere file di grandi dimensioni con decine di migliaia fino a un massimo di un milione di caratteri?

Assicurati di allocare un buffer sufficientemente grande:

 BufferedWriter out = new BufferedWriter(new FileWriter(file), 32768); 

Su quale tipo di OS stai correndo? Anche questo può fare una grande differenza. Tuttavia, prendere un minuto per scrivere un file di dimensioni non enormi può sembrare un problema di sistema. Su Linux o su altri sistemi * ix, puoi usare cose come strace per vedere se la JVM sta facendo molte chiamate di sistema non necessarie. (Molto tempo fa, Java I / O era piuttosto stupido e avrebbe creato un folle numero di chiamate di sistema write() di basso livello se non si stava attenti, ma quando dico “tanto tempo fa” intendo nel 1998 circa .)

modifica – nota che la situazione di un programma Java che scrive un semplice file in un modo semplice, e tuttavia essendo molto lento, è intrinsecamente dispari. Puoi dire se la CPU è pesantemente caricata mentre il file è in fase di scrittura? Non dovrebbe essere; non ci dovrebbe essere quasi nessun carico della CPU da una cosa del genere.

Un semplice test per te

 char[] chars = new char[100*1024*1024]; Arrays.fill(chars, 'A'); String text = new String(chars); long start = System.nanoTime(); BufferedWriter bw = new BufferedWriter(new FileWriter("/tmp/a.txt")); bw.write(text); bw.close(); long time = System.nanoTime() - start; System.out.println("Wrote " + chars.length*1000L/time+" MB/s."); 

stampe

 Wrote 135 MB/s. 

Potresti esaminare le funzionalità NIO di Java. Può supportare ciò che vuoi fare.

Java NIO FileChannel contro prestazioni / utilità di FileOutputstream

Prova a utilizzare i file mappati in memoria:

 FileChannel rwChannel = new RandomAccessFile("textfile.txt", "rw").getChannel(); ByteBuffer wrBuf = rwChannel.map(FileChannel.MapMode.READ_WRITE, 0, textToSave.length()); wrBuf.put(textToSave.getBytes()); rwChannel.close(); 

Ciao Ho creato due approcci per creare file di grandi dimensioni, eseguire programmi su Windows 7, 64-bit, 8 GB di RAM, JDK 8 e sotto sono risultati.
In entrambi i casi, viene creato un file di 180 MB contenente il numero in ciascuna riga da 1 a 20 milioni (2 crore nel sistema indiano).

La memoria del programma Java cresce gradualmente fino a 600 MB

Prima uscita

 Approach = approach-1 (Using FileWriter) Completed file writing in milli seconds = 4521 milli seconds. 

Seconda uscita

 Approach = approach-2 (Using FileChannel and ByteBuffer) Completed file writing in milli seconds = 3590 milli seconds. 

Un’osservazione – Sto calcolando la posizione (variabile pos) nell’approccio # 2, se commento fuori allora solo l’ultima stringa sarà visibile a causa della sovrascrittura in posizione, ma il tempo ridotto a quasi 2000 milli secondi.

Albind il codice.

 import java.io.FileWriter; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.util.concurrent.TimeUnit; public class TestLargeFile { public static void main(String[] args) { writeBigFile(); } private static void writeBigFile() { System.out.println("--------writeBigFile-----------"); long nanoTime = System.nanoTime(); String fn = "big-file.txt"; boolean approach1 = false; System.out.println("Approach = " + (approach1 ? "approach-1" : "approach-2")); int numLines = 20_000_000; try { if (approach1) { //Approach 1 -- for 2 crore lines takes 4.5 seconds with 180 mb file size approach1(fn, numLines); } else { //Approach 2 -- for 2 crore lines takes nearly 2 to 2.5 seconds with 180 mb file size approach2(fn, numLines); } } catch (IOException e) { e.printStackTrace(); } System.out.println("Completed file writing in milli seconds = " + TimeUnit.MILLISECONDS.convert((System.nanoTime() - nanoTime), TimeUnit.NANOSECONDS)); } private static void approach2(String fn, int numLines) throws IOException { StringBuilder sb = new StringBuilder(); FileChannel rwChannel = new RandomAccessFile(fn, "rw").getChannel(); ByteBuffer wrBuf; int pos = 0; for (int i = 1; i <= numLines; i++) { sb.append(i).append(System.lineSeparator()); if (i % 100000 == 0) { wrBuf = rwChannel.map(FileChannel.MapMode.READ_WRITE, pos, sb.length()); pos += sb.length(); wrBuf.put(sb.toString().getBytes()); sb = new StringBuilder(); } } if (sb.length() > 0) { wrBuf = rwChannel.map(FileChannel.MapMode.READ_WRITE, pos, sb.length()); wrBuf.put(sb.toString().getBytes()); } rwChannel.close(); } private static void approach1(String fn, int numLines) throws IOException { StringBuilder sb = new StringBuilder(); for (int i = 1; i <= numLines; i++) { sb.append(i).append(System.lineSeparator()); } FileWriter fileWriter = new FileWriter(fn); fileWriter.write(sb.toString()); fileWriter.flush(); fileWriter.close(); } } 

In Java, BufferWriter è molto lento: usa direttamente i metodi nativi e chiamali il meno ansible (dai loro più dati per chiamata che puoi).

  try{ FileOutputStream file=new FileOutputStream(file); file.write(content); file.close(); }catch(Throwable e){ D.error(e); }//try 

Inoltre, l’eliminazione del file può richiedere un po ‘di tempo (potrebbe essere prima copiata nel cestino). Basta sovrascrivere il file, come nel codice precedente.