Je dois lire un gros fichier texte d'environ 5-6 Go ligne par ligne en utilisant Java.
Comment puis-je faire cela rapidement?
Je dois lire un gros fichier texte d'environ 5-6 Go ligne par ligne en utilisant Java.
Comment puis-je faire cela rapidement?
Un motif commun est d'utiliser
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String line;
while ((line = br.readLine()) != null) {
// process the line.
}
}
Vous pouvez lire les données plus rapidement si vous supposez qu'il n'y a pas de codage de caractères. par exemple ASCII-7 mais cela ne fera pas beaucoup de différence. Il est très probable que ce que vous faites avec les données prendra beaucoup plus de temps.
MODIFICATION : Un motif moins courant à utiliser qui évite la fuite de portée de line
.
try(BufferedReader br = new BufferedReader(new FileReader(file))) {
for(String line; (line = br.readLine()) != null; ) {
// process the line.
}
// line n'est pas visible ici.
}
MISE À JOUR : En Java 8, vous pouvez faire
try (Stream stream = Files.lines(Paths.get(fileName))) {
stream.forEach(System.out::println);
}
REMARQUE : Vous devez placer le Stream dans un bloc try-with-resource pour garantir que la méthode #close est appelée dessus, sinon la poignée de fichier sous-jacente ne sera jamais fermée jusqu'à ce que GC le fasse beaucoup plus tard.
A quoi ressemble ce motif avec une gestion appropriée des exceptions? Je remarque que br.close() lance une IOException, ce qui semble surprenant - que pourrait-il se passer lors de la fermeture d'un fichier ouvert en lecture, de toute façon? Le constructeur de FileReader pourrait générer une exception FileNotFound.
@MikeB En Java 7, vous ajouteriez un bloc try-with-resource. Close ne devrait pas déclencher d'exception, mais certaines implémentations pourraient le faire. Je ne m'attendrais pas à ce que BufferedReader en fasse partie. Il est très rare de voir les développeurs ajouter un traitement spécial pour close();
Est-ce la vitesse maximale que Java peut atteindre ? J'ai un fichier d'environ 200 Mo que je lis avec cette méthode et c'est vraiment lent ... est-il possible d'utiliser quelque chose de plus rapide ? Lire sur plusieurs lignes ou quelque chose du genre ?
Regardez ce blog :
La taille du tampon peut être spécifiée, ou la taille par défaut peut être utilisée. Par défaut, elle est suffisamment grande pour la plupart des besoins.
// Ouvrir le fichier
FileInputStream fstream = new FileInputStream("textfile.txt");
// Obtenez l'objet DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
// Lire le fichier ligne par ligne
while ((strLine = br.readLine()) != null) {
// Afficher le contenu sur la console
System.out.println (strLine);
}
// Fermer le flux d'entrée
in.close();
Mon fichier fait 1,5 Gig et il n'est pas possible de lire le fichier en utilisant votre réponse!
Downvoted pour la piètre qualité du lien. Il y a une DataInputStream
totalement inutile, et le mauvais flux est fermé. Rien de mal avec le tutoriel Java, et pas besoin de citer des absurdités arbitraires de tiers sur Internet comme ça.
Une fois que Java 8 est sorti (mars 2014), vous pourrez utiliser des flux :
try (Stream lines = Files.lines(Paths.get(filename), Charset.defaultCharset())) {
lines.forEachOrdered(line -> process(line));
}
Imprimer toutes les lignes dans le fichier :
try (Stream lines = Files.lines(file, Charset.defaultCharset())) {
lines.forEachOrdered(System.out::println);
}
Utilisez StandardCharsets.UTF_8
, utilisez Stream
pour la concision, et évitez d'utiliser forEach()
et surtout forEachOrdered()
sauf s'il y a une raison.
Si j'utilise forEach au lieu de forEachOrdered, les lignes pourraient être imprimées dans le désordre, n'est-ce pas?
Voici un exemple avec une gestion d'erreur complète et la spécification de jeu de caractères pour les versions antérieures à Java 7. Avec Java 7, vous pouvez utiliser la syntaxe try-with-resources, ce qui rend le code plus propre.
Si vous voulez juste utiliser le jeu de caractères par défaut, vous pouvez sauter l'entrée InputStream et utiliser FileReader.
InputStream ins = null; // raw byte-stream
Reader r = null; // cooked reader
BufferedReader br = null; // tamponné pour readLine()
try {
String s;
if (true) {
String data = "#foobar\t1234\n#xyz\t5678\none\ttwo\n";
ins = new ByteArrayInputStream(data.getBytes());
} else {
ins = new FileInputStream("textfile.txt");
}
r = new InputStreamReader(ins, "UTF-8"); // laisser le jeu de caractères par défaut
br = new BufferedReader(r);
while ((s = br.readLine()) != null) {
System.out.println(s);
}
}
catch (Exception e)
{
System.err.println(e.getMessage()); // gérer l'exception
}
finally {
if (br != null) { try { br.close(); } catch(Throwable t) { /* assurer la fermeture */ } }
if (r != null) { try { r.close(); } catch(Throwable t) { /* assurer la fermeture */ } }
if (ins != null) { try { ins.close(); } catch(Throwable t) { /* assurer la fermeture */ } }
}
Voici la version Groovy, avec une gestion d'erreur complète :
File f = new File("textfile.txt");
f.withReader("UTF-8") { br ->
br.eachLine { line ->
println line;
}
}
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
83 votes
@kamaci et al. Cette question ne devrait pas être marquée comme un doublon. "Lire rapidement la dernière ligne" n'est pas une alternative, et il est discutable de savoir si "Manière la plus rapide de lire un fichier texte ligne par ligne" en est une. La manière la plus rapide de faire quelque chose n'est pas forcément la manière la plus commune. De plus, les réponses ci-dessous incluent du code, alors que l'alternative la plus pertinente que vous mentionnez ne le fait pas. Cette question est utile. Elle est actuellement en tête des résultats de recherche Google pour "java lire un fichier ligne par ligne". Enfin, il est décourageant d'arriver sur stack overflow et de constater que 1 question sur 2 est signalée pour être éliminée.
5 votes
Ici se trouve une comparaison de vitesse pour six implémentations possibles.
5 votes
Même si j'ai lu des commentaires argumentant que la politique de fermeture de SO est nulle, SO persiste. C'est une vision de développeur étroite d'esprit de vouloir éviter la redondance à tout prix! Laissez faire! La crème remontera naturellement et la m*rde coulera d'elle-même vers le bas. Même si une question a déjà été posée avant (quelle question ne l'a pas été ??), cela ne signifie pas qu'une nouvelle question ne pourrait pas la formuler mieux, obtenir de meilleures réponses, être mieux classée dans les moteurs de recherche, etc. D'ailleurs, cette question est maintenant 'protégée'...
4 votes
C'est incroyable comment les questions sont marquées comme doublon en lisant simplement le titre.
0 votes
Après l'édition de Shog, il s'agit en effet d'un doublon de stackoverflow.com/q/5800361/103167 mais celui-ci a suscité beaucoup plus d'activité.