Lire tout le texte d'un fichier
Java 11 a ajouté le readString() pour lire les petits fichiers en tant que String
en préservant les terminaisons de ligne :
String content = Files.readString(path, StandardCharsets.US_ASCII);
Pour les versions entre Java 7 et 11, voici un idiome compact et robuste, emballé dans une méthode utilitaire :
static String readFile(String path, Charset encoding)
throws IOException
{
byte[] encoded = Files.readAllBytes(Paths.get(path));
return new String(encoded, encoding);
}
Lire les lignes de texte d'un fichier
Java 7 a ajouté un Méthode pratique pour lire un fichier sous forme de lignes de texte, représenté par un List<String>
. Cette approche est "avec perte" car les séparateurs de ligne sont supprimés à la fin de chaque ligne.
List<String> lines = Files.readAllLines(Paths.get(path), encoding);
Java 8 a ajouté le Files.lines()
pour produire un Stream<String>
. Là encore, cette méthode entraîne des pertes car les séparateurs de ligne sont supprimés. Si un IOException
est rencontrée lors de la lecture du fichier, elle est enveloppée dans un fichier de type UncheckedIOException
puisque Stream
n'accepte pas les lambdas qui lèvent des exceptions vérifiées.
try (Stream<String> lines = Files.lines(path, encoding)) {
lines.forEach(System.out::println);
}
Ce site Stream
a besoin d'un close()
ce qui est mal documenté dans l'API, et je pense que beaucoup de personnes ne le remarquent même pas. Stream
a un close()
méthode. Veillez à utiliser un bloc ARM comme indiqué.
Si vous travaillez avec une source autre qu'un fichier, vous pouvez utiliser la fonction lines()
méthode dans BufferedReader
à la place.
Utilisation de la mémoire
La première méthode, qui préserve les sauts de ligne, peut temporairement nécessiter une mémoire plusieurs fois supérieure à la taille du fichier, car pendant un court instant, le contenu brut du fichier (un tableau d'octets) et les caractères décodés (chacun d'entre eux comporte 16 bits même s'ils sont codés sur 8 bits dans le fichier) résident en mémoire en même temps. Il est plus sûr de s'appliquer à des fichiers que vous savez être petits par rapport à la mémoire disponible.
La deuxième méthode, la lecture des lignes, est généralement plus efficace en termes de mémoire, car le tampon d'octets d'entrée pour le décodage n'a pas besoin de contenir le fichier entier. Cependant, elle n'est toujours pas adaptée aux fichiers qui sont très volumineux par rapport à la mémoire disponible.
Pour lire des fichiers volumineux, vous devez concevoir un programme différent, qui lit un morceau de texte dans un flux, le traite, puis passe au suivant, en réutilisant le même bloc de mémoire de taille fixe. Ici, le terme "gros" dépend des spécifications de l'ordinateur. De nos jours, ce seuil peut correspondre à plusieurs gigaoctets de RAM. La troisième méthode, qui utilise un Stream<String>
est une façon de le faire, si vos "enregistrements" d'entrée sont des lignes individuelles. (En utilisant la fonction readLine()
méthode de BufferedReader
est l'équivalent procédural de cette approche).
Codage des caractères
Une chose qui manque dans l'échantillon de l'article original est le codage des caractères. Il existe des cas particuliers où la plateforme par défaut est ce que vous voulez, mais ils sont rares, et vous devriez pouvoir justifier votre choix.
El StandardCharsets
La classe définit certaines constantes pour les codages requis par tous les moteurs d'exécution Java :
String content = readFile("test.txt", StandardCharsets.UTF_8);
La plateforme par défaut est disponible à partir de le site Charset
classe lui-même :
String content = readFile("test.txt", Charset.defaultCharset());
Note : Cette réponse remplace en grande partie ma version de Java 6. L'utilité de Java 7 simplifie considérablement le code et l'ancienne réponse, qui utilisait un tampon d'octets mappé, empêchait la suppression du fichier lu jusqu'à ce que le tampon mappé soit vidé. Vous pouvez voir l'ancienne version via le lien "edited" sur cette réponse.
7 votes
Quelqu'un peut-il m'expliquer de manière très simple ce qu'est le NIO ? Chaque fois que je lis quelque chose à ce sujet, je me perds dans la énième mention du canal :(
7 votes
N'oubliez pas qu'il n'est pas garanti que le séparateur de ligne du fichier ne soit pas nécessairement le même que le séparateur de ligne du système.
6 votes
Le code ci-dessus a un bug qui consiste à ajouter un caractère supplémentaire à la dernière ligne. Il devrait être quelque chose comme suit if(line = reader.readLine() ) != null){ stringBuilder.append( line ) ; } while (line = reader.readLine() ) != null) { stringBuilder.append( ls ) ; stringBuilder.append( line ) ; }
29 votes
Java 7 introduit
byte[] Files.readAllBytes(file);
À ceux qui suggèrent la solution du scanner "à une ligne" : Ne devez-vous pas le fermer ?0 votes
@OscarRyz Le plus grand changement pour moi est que NIO vous permet d'écouter de nombreux ports sans allouer un thread pour chacun. Ce n'est pas un problème, sauf si vous voulez envoyer un paquet à chaque machine dans un espace d'adresse de réseau de classe B (65k adresses) pour voir ce qui existe, Windows est à court de threads à environ 20k (j'ai découvert cela en résolvant exactement ce problème - la découverte d'un réseau de classe A/B, avant NIO c'était difficile).
0 votes
Si vous voyez l'implémentation de Files.readAllBytes(), vous remarquerez qu'elle utilise un canal qui peut être fermé. Il n'est donc pas nécessaire de le fermer explicitement.
0 votes
Avec l'avènement de Groovy, vous pouvez lire le fichier ainsi : return new File( fichier).text()
0 votes
Lien vers un autre lien StackOverflow, qui trouve que c'est bien expliqué : stackoverflow.com/questions/14169661/
0 votes
@Deep La dernière ligne d'un fichier texte est généralement terminée par une ligne, donc ce que vous décrivez comme un bug n'en est pas un, et votre code a le bug d'enlever todo les terminaisons de ligne.
0 votes
Veuillez accepter une réponse à votre question et aider à mettre fin à cette situation.