J'ai créé une méthode qui prend une File
et une String
. Il remplace le fichier par un nouveau fichier contenant cette chaîne.
Voici ce que j'ai fait:
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) {
}
}
Cependant, il est douloureusement lent. Cela prend parfois plus d'une minute.
Comment puis-je écrire des fichiers volumineux contenant des dizaines de milliers voire un million de caractères?
Assurez-vous d’allouer un tampon suffisamment grand:
BufferedWriter out = new BufferedWriter(new FileWriter(file), 32768);
Quel type de système d'exploitation utilisez-vous? Cela peut aussi faire une grande différence. Cependant, prendre minute pour écrire un fichier de taille inférieure à énorme ressemble à un problème système. Sur Linux ou d’autres systèmes * ix, vous pouvez utiliser des éléments tels que strace
pour voir si la JVM effectue de nombreux appels système inutiles. (Il y a très longtemps, Java I/O était plutôt stupide et émettait un nombre insensé d'appels système write()
de bas niveau si vous ne faisiez pas attention, mais quand je dis "il y a longtemps", je veux dire 1998 ou plus.)
edit - notez que la situation d'un programme Java écrivant un fichier simple de manière simple, et pourtant très lente, est par nature étrange. Pouvez-vous dire si le processeur est lourdement chargé pendant l'écriture du fichier? Cela ne devrait pas être; il devrait y avoir presque pas de charge de processeur d'une telle chose.
Un test simple pour vous
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.");
Impressions
Wrote 135 MB/s.
Vous pouvez examiner les capacités de Java NIO. Cela peut soutenir ce que vous voulez faire.
Java NIO FileChannel vs FileOutputstream performance/utilité
Essayez d’utiliser des fichiers mappés en mémoire:
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();
Bonjour, j'ai créé deux approches pour créer de gros fichiers, exécuter le programme sur Windows 7, 64 bits, 8 Go RAM machine, JDK 8 et moins sont des résultats.
Dans les deux cas, fichier de 180 Mo créé contenant un nombre dans chaque ligne de 1 à 20 millions (2 crore dans le système indien).
La mémoire du programme Java augmente progressivement jusqu'à 600 Mo
Première sortie
Approach = approach-1 (Using FileWriter)
Completed file writing in milli seconds = 4521 milli seconds.
Deuxième sortie
Approach = approach-2 (Using FileChannel and ByteBuffer)
Completed file writing in milli seconds = 3590 milli seconds.
Une observation - Je calcule la position (variable pos) dans l'approche n ° 2; si je la commente, seule la dernière chaîne sera visible car elle est écrasée à la position, mais le temps est réduit à près de 2000 millisecondes.
Code attaché.
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();
}
}