Comment créer une chaîne Java à partir du contenu d’un fichier?

J’utilise l’idiome ci-dessous depuis un certain temps maintenant. Et cela semble être le plus répandu, du moins sur les sites que j’ai visités.

Existe-t-il une manière différente / meilleure de lire un fichier dans une chaîne en Java?

private Ssortingng readFile(Ssortingng file) throws IOException { BufferedReader reader = new BufferedReader(new FileReader (file)); Ssortingng line = null; SsortingngBuilder ssortingngBuilder = new SsortingngBuilder(); Ssortingng ls = System.getProperty("line.separator"); try { while((line = reader.readLine()) != null) { ssortingngBuilder.append(line); ssortingngBuilder.append(ls); } return ssortingngBuilder.toSsortingng(); } finally { reader.close(); } } 

Lire tout le texte d’un fichier

Voici un idiome compact et robuste pour Java 7, inclus dans une méthode utilitaire:

 static Ssortingng readFile(Ssortingng path, Charset encoding) throws IOException { byte[] encoded = Files.readAllBytes(Paths.get(path)); return new Ssortingng(encoded, encoding); } 

Lire les lignes de texte d’un fichier

Java 7 a ajouté une méthode pratique pour lire un fichier sous forme de lignes de texte, représentées sous la forme d’une List . Cette approche est “avec perte” car les séparateurs de lignes sont supprimés de la fin de chaque ligne.

 List lines = Files.readAllLines(Paths.get(path), encoding); 

Dans Java 8, BufferedReader ajouté une nouvelle méthode, lines() pour générer un Stream . Si une IOException est rencontrée lors de la lecture du fichier, elle est encapsulée dans une exception UncheckedIOException , car Stream n’accepte pas les lambdas qui lancent des exceptions vérifiées.

 try (BufferedReader r = Files.newBufferedReader(path, encoding)) { r.lines().forEach(System.out::println); } 

Il y a aussi une méthode Files.lines() qui fait quelque chose de très similaire, renvoyant directement le Stream . Mais je n’aime pas ça. Le Stream nécessite un appel close() ; Ceci est mal documenté sur l’API, et je pense que beaucoup de gens ne remarquent même pas que Stream a une méthode close() . Donc, votre code serait très similaire, comme ceci:

 try (Stream lines = Files.lines(path, encoding)) { lines.forEach(System.out::println); } 

La différence est que vous avez un Stream assigné à une variable, et j’essaie d’éviter cela comme une pratique afin de ne pas tenter accidentellement d’appeler le stream deux fois.

Utilisation de la mémoire

La première méthode, qui préserve les sauts de ligne, peut nécessiter temporairement de la mémoire plusieurs fois la taille du fichier, car pendant une courte période le contenu du fichier brut (un tableau d’octets) et les caractères décodés (chacun comme 8 bits dans le fichier) résident en mémoire à la fois. Il est plus sûr d’appliquer aux fichiers dont vous savez qu’ils sont petits par rapport à la mémoire disponible.

La seconde méthode, les lignes de lecture, est généralement plus efficace en termes de mémoire, car le tampon d’octet d’entrée pour le décodage n’a pas besoin de contenir la totalité du fichier. Cependant, il ne convient toujours pas aux fichiers très volumineux par rapport à la mémoire disponible.

Pour lire des fichiers volumineux, vous devez utiliser une conception différente pour votre programme, qui lit un morceau de texte à partir d’un stream, le traite et passe ensuite au suivant, réutilisant le même bloc de mémoire de taille fixe. Ici, “grand” dépend des spécifications de l’ordinateur. De nos jours, ce seuil pourrait être de plusieurs gigaoctets de RAM. La troisième méthode, qui utilise un Stream est un moyen d’y parvenir si vos “enregistrements” en entrée se trouvent être des lignes individuelles. (L’utilisation de la méthode readLine() de BufferedReader est l’équivalent procédural de cette approche.)

Encodage de caractère

Une chose qui manque dans l’exemple dans l’article d’origine est le codage des caractères. Il y a 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.

La classe StandardCharsets définit des constantes pour les codages requirejs pour tous les environnements d’exécution Java:

 Ssortingng content = readFile("test.txt", StandardCharsets.UTF_8); 

La plate-forme par défaut est disponible dans la classe Charset elle – même:

 Ssortingng content = readFile("test.txt", Charset.defaultCharset()); 

Remarque: cette réponse remplace largement ma version Java 6. L’utilitaire de Java 7 simplifie le code en toute sécurité 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 nettoyé. Vous pouvez voir l’ancienne version via le lien “édité” sur cette réponse.

Commons FileUtils.readFileToSsortingng :

 public static Ssortingng readFileToSsortingng(File file) throws IOException 

Lit le contenu d’un fichier dans une chaîne en utilisant le codage par défaut pour la machine virtuelle. Le fichier est toujours fermé.

Paramètres:

  • file – le fichier à lire ne doit pas être nul

Retourne: le contenu du fichier, jamais nul

Lance: – IOException – en cas d’erreur d’E / S

Depuis: Commons IO 1.3.1

Le code utilisé (indirectement) par cette classe est:

IOUtils.java sous licence Apache 2.0 .

 public static long copyLarge(InputStream input, OutputStream output) throws IOException { byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; long count = 0; int n = 0; while (-1 != (n = input.read(buffer))) { output.write(buffer, 0, n); count += n; } return count; } 

Il est très similaire à celui utilisé par Ritche_W.

De cette page une solution très maigre:

 Scanner scanner = new Scanner( new File("poem.txt") ); Ssortingng text = scanner.useDelimiter("\\A").next(); scanner.close(); // Put this call in a finally block 

ou

 Scanner scanner = new Scanner( new File("poem.txt"), "UTF-8" ); Ssortingng text = scanner.useDelimiter("\\A").next(); scanner.close(); // Put this call in a finally block 

Si vous souhaitez définir le jeu de caractères

Si vous recherchez une alternative sans bibliothèque tierce (par exemple, Commons I / O ), vous pouvez utiliser la classe Scanner :

 private Ssortingng readFile(Ssortingng pathname) throws IOException { File file = new File(pathname); SsortingngBuilder fileContents = new SsortingngBuilder((int)file.length()); Scanner scanner = new Scanner(file); Ssortingng lineSeparator = System.getProperty("line.separator"); try { while(scanner.hasNextLine()) { fileContents.append(scanner.nextLine() + lineSeparator); } return fileContents.toSsortingng(); } finally { scanner.close(); } } 

Guava a une méthode similaire à celle de Commons IOUtils que Willi aus Rohr a mentionnée:

 import com.google.common.base.Charsets; import com.google.common.io.Files; // ... Ssortingng text = Files.toSsortingng(new File(path), Charsets.UTF_8); 

EDIT par Oscar Reyes

Ceci est le code sous-jacent (simplifié) de la bibliothèque citée:

 InputStream in = new FileInputStream(file); byte[] b = new byte[file.length()]; int len = b.length; int total = 0; while (total < len) { int result = in.read(b, total, len - total); if (result == -1) { break; } total += result; } return new String( b , Charsets.UTF_8 ); 

Edit (par Jonik): Ce qui précède ne correspond pas au code source des versions récentes de Guava. Pour la source actuelle, voir les classes Files , CharStreams , ByteSource et CharSource dans le package com.google.common.io .

 import java.nio.file.Files; 

…….

  Ssortingng readFile(Ssortingng filename) { File f = new File(filename); try { byte[] bytes = Files.readAllBytes(f.toPath()); return new Ssortingng(bytes,"UTF-8"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return ""; } 

Si vous avez besoin d’un traitement de chaîne (parallel processing), Java 8 dispose de la bonne API Stream.

 Ssortingng result = Files.lines(Paths.get("file.txt")) .parallel() // for parallel processing .map(Ssortingng::sortingm) // to change line .filter(line -> line.length() > 2) // to filter some lines by a predicate .collect(Collectors.joining()); // to join lines 

D’autres exemples sont disponibles dans les exemples JDK: sample/lambda/BulkDataOperations qui peuvent être téléchargés depuis la page de téléchargement Oracle Java SE 8

Un autre exemple de ligne

 Ssortingng out = Ssortingng.join("\n", Files.readAllLines(Paths.get("file.txt"))); 

Ce code va normaliser les sauts de ligne, qui peuvent ou non être ce que vous voulez vraiment faire.

Voici une alternative qui ne fait pas cela, et qui est (IMO) plus simple à comprendre que le code NIO (bien qu’il utilise toujours java.nio.charset.Charset ):

 public static Ssortingng readFile(Ssortingng file, Ssortingng csName) throws IOException { Charset cs = Charset.forName(csName); return readFile(file, cs); } public static Ssortingng readFile(Ssortingng file, Charset cs) throws IOException { // No real need to close the BufferedReader/InputStreamReader // as they're only wrapping the stream FileInputStream stream = new FileInputStream(file); try { Reader reader = new BufferedReader(new InputStreamReader(stream, cs)); SsortingngBuilder builder = new SsortingngBuilder(); char[] buffer = new char[8192]; int read; while ((read = reader.read(buffer, 0, buffer.length)) > 0) { builder.append(buffer, 0, read); } return builder.toSsortingng(); } finally { // Potential issue here: if this throws an IOException, // it will mask any others. Normally I'd use a utility // method which would log exceptions and swallow them stream.close(); } } 
 Ssortingng content = new Ssortingng(Files.readAllBytes(Paths.get("readMe.txt")), "UTF-8"); 

Depuis Java 7, vous pouvez le faire de cette façon.

Si c’est un fichier texte, pourquoi ne pas utiliser apache commons-io ?

Il a la méthode suivante

 public static Ssortingng readFileToSsortingng(File file) throws IOException 

Si vous voulez que les lignes soient utilisées comme liste

 public static List readLines(File file) throws IOException 

Java tente d’être extrêmement général et flexible dans tout ce qu’il fait. En conséquence, quelque chose de relativement simple dans un langage de script (votre code serait remplacé par ” open(file).read() ” en python) est beaucoup plus compliqué. Il ne semble pas y avoir de moyen plus court de le faire, sauf en utilisant une bibliothèque externe (comme Willi aus Rohr mentionné). Vos options:

  • Utilisez une bibliothèque externe.
  • Copiez ce code dans tous vos projets.
  • Créez votre propre mini-bibliothèque contenant les fonctions que vous utilisez souvent.

Votre meilleur pari est probablement le 2ème, car il a le moins de dépendances.

Pour lire un fichier en binary et le convertir à la fin

 public static Ssortingng readFileAsSsortingng(Ssortingng filePath) throws IOException { DataInputStream dis = new DataInputStream(new FileInputStream(filePath)); try { long len = new File(filePath).length(); if (len > Integer.MAX_VALUE) throw new IOException("File "+filePath+" too large, was "+len+" bytes."); byte[] bytes = new byte[(int) len]; dis.readFully(bytes); return new Ssortingng(bytes, "UTF-8"); } finally { dis.close(); } } 

Avec Java 7, ceci est mon option préférée pour lire un fichier UTF-8:

 Ssortingng content = new Ssortingng(Files.readAllBytes(Paths.get(filename)), "UTF-8"); 

Depuis Java 7, le JDK a la nouvelle API java.nio.file , qui fournit de nombreux raccourcis, de sorte que les bibliothèques tierces ne sont pas toujours requirejses pour les opérations de fichiers simples.

Il existe une variante du même thème qui utilise une boucle for, au lieu d’une boucle while, pour limiter la scope de la variable de ligne. Que ce soit “mieux” est une question de goût personnel.

 for(Ssortingng line = reader.readLine(); line != null; line = reader.readLine()) { ssortingngBuilder.append(line); ssortingngBuilder.append(ls); } 

Depuis JDK 11:

 Ssortingng file = ... Path path = Paths.get(file); Ssortingng content = Files.readSsortingng(path); // Or readSsortingng(path, someCharset), if you need a Charset different from UTF-8 
 public static Ssortingng slurp (final File file) throws IOException { SsortingngBuilder result = new SsortingngBuilder(); try { BufferedReader reader = new BufferedReader(new FileReader(file)); char[] buf = new char[1024]; int r = 0; while ((r = reader.read(buf)) != -1) { result.append(buf, 0, r); } } finally { reader.close(); } return result.toSsortingng(); } 

Si vous n’avez pas access aux fichiers, procédez comme suit:

 static Ssortingng readFile(File file, Ssortingng charset) throws IOException { FileInputStream fileInputStream = new FileInputStream(file); byte[] buffer = new byte[fileInputStream.available()]; int length = fileInputStream.read(buffer); fileInputStream.close(); return new Ssortingng(buffer, 0, length, charset); } 

Une solution flexible utilisant IOUtils d’Apache commons-io en combinaison avec SsortingngWriter :

 Reader input = new FileReader(); SsortingngWriter output = new SsortingngWriter(); try { IOUtils.copy(input, output); } finally { input.close(); } Ssortingng fileContents = output.toSsortingng(); 

Il fonctionne avec n’importe quel lecteur ou stream d’entrée (pas uniquement avec les fichiers), par exemple lors de la lecture d’une URL.

Sachez que lorsque vous utilisez fileInputStream.available() l’entier renvoyé ne doit pas nécessairement représenter la taille réelle du fichier, mais plutôt la quantité d’octets supposée que le système devrait pouvoir lire à partir du stream sans bloquer IO. Un moyen simple et sûr pourrait ressembler à ceci

 public Ssortingng readSsortingngFromInputStream(FileInputStream fileInputStream) { SsortingngBuffer ssortingngBuffer = new SsortingngBuffer(); try { byte[] buffer; while (fileInputStream.available() > 0) { buffer = new byte[fileInputStream.available()]; fileInputStream.read(buffer); ssortingngBuffer.append(new Ssortingng(buffer, "ISO-8859-1")); } } catch (FileNotFoundException e) { } catch (IOException e) { } return ssortingngBuffer.toSsortingng(); } 

Il convient de considérer que cette approche ne convient pas aux codages de caractères multi-octets tels que UTF-8.

Celui-ci utilise la méthode RandomAccessFile.readFully , il semble être disponible à partir de JDK 1.0!

 public static Ssortingng readFileContent(Ssortingng filename, Charset charset) throws IOException { RandomAccessFile raf = null; try { raf = new RandomAccessFile(filename, "r"); byte[] buffer = new byte[(int)raf.length()]; raf.readFully(buffer); return new Ssortingng(buffer, charset); } finally { closeStream(raf); } } private static void closeStream(Closeable c) { if (c != null) { try { c.close(); } catch (IOException ex) { // do nothing } } } 

Vous pouvez essayer la classe Scanner et File, une solution en quelques lignes

  try { Ssortingng content = new Scanner(new File("file.txt")).useDelimiter("\\Z").next(); System.out.println(content); } catch(FileNotFoundException e) { System.out.println("not found!"); } 

Rassembler toutes les façons possibles de lire le fichier en tant que chaîne à partir du disque ou du réseau.

  • Goyave: Google utilisant des classes Resources , Files

     static Charset charset = com.google.common.base.Charsets.UTF_8; public static Ssortingng guava_ServerFile( URL url ) throws IOException { return Resources.toSsortingng( url, charset ); } public static Ssortingng guava_DiskFile( File file ) throws IOException { return Files.toSsortingng( file, charset ); } 

  • APACHE – COMMONS IO utilisant les classes IOUtils, FileUtils

     static Charset encoding = org.apache.commons.io.Charsets.UTF_8; public static Ssortingng commons_IOUtils( URL url ) throws IOException { java.io.InputStream in = url.openStream(); try { return IOUtils.toSsortingng( in, encoding ); } finally { IOUtils.closeQuietly(in); } } public static Ssortingng commons_FileUtils( File file ) throws IOException { return FileUtils.readFileToSsortingng( file, encoding ); /*List lines = FileUtils.readLines( fileName, encoding ); return lines.stream().collect( Collectors.joining("\n") );*/ } 

  • Java 8 BufferReader à l’ aide de l’ API Stream

     public static Ssortingng streamURL_Buffer( URL url ) throws IOException { java.io.InputStream source = url.openStream(); BufferedReader reader = new BufferedReader( new InputStreamReader( source ) ); //List lines = reader.lines().collect( Collectors.toList() ); return reader.lines().collect( Collectors.joining( System.lineSeparator() ) ); } public static Ssortingng streamFile_Buffer( File file ) throws IOException { BufferedReader reader = new BufferedReader( new FileReader( file ) ); return reader.lines().collect(Collectors.joining(System.lineSeparator())); } 

  • Scanner Class avec regex \A qui correspond au début de l’entrée.

     static Ssortingng charsetName = java.nio.charset.StandardCharsets.UTF_8.toSsortingng(); public static Ssortingng streamURL_Scanner( URL url ) throws IOException { java.io.InputStream source = url.openStream(); Scanner scanner = new Scanner(source, charsetName).useDelimiter("\\A"); return scanner.hasNext() ? scanner.next() : ""; } public static Ssortingng streamFile_Scanner( File file ) throws IOException { Scanner scanner = new Scanner(file, charsetName).useDelimiter("\\A"); return scanner.hasNext() ? scanner.next() : ""; } 

  • Java 7 ( java.nio.file.Files.readAllBytes )

     public static Ssortingng getDiskFile_Java7( File file ) throws IOException { byte[] readAllBytes = java.nio.file.Files.readAllBytes(Paths.get( file.getAbsolutePath() )); return new Ssortingng( readAllBytes ); } 

  • BufferedReader utilisant InputStreamReader .

     public static Ssortingng getDiskFile_Lines( File file ) throws IOException { SsortingngBuffer text = new SsortingngBuffer(); FileInputStream fileStream = new FileInputStream( file ); BufferedReader br = new BufferedReader( new InputStreamReader( fileStream ) ); for ( Ssortingng line; (line = br.readLine()) != null; ) text.append( line + System.lineSeparator() ); return text.toSsortingng(); } 

Exemple avec la méthode principale pour accéder aux méthodes ci-dessus.

 public static void main(Ssortingng[] args) throws IOException { Ssortingng fileName = "E:/parametarisation.csv"; File file = new File( fileName ); Ssortingng fileStream = commons_FileUtils( file ); // guava_DiskFile( file ); // streamFile_Buffer( file ); // getDiskFile_Java7( file ); // getDiskFile_Lines( file ); System.out.println( " File Over Disk : \n"+ fileStream ); try { Ssortingng src = "https://code.jquery.com/jquery-3.2.1.js"; URL url = new URL( src ); Ssortingng urlStream = commons_IOUtils( url ); // guava_ServerFile( url ); // streamURL_Scanner( url ); // streamURL_Buffer( url ); System.out.println( " File Over Network : \n"+ urlStream ); } catch (MalformedURLException e) { e.printStackTrace(); } } 

@voir

  • Façons de convertir un InputStream en une chaîne

Après Ctrl + F’ing après Scanner, je pense que la solution Scanner doit également être répertoriée. Dans la façon la plus facile à lire, ça se passe comme ceci:

 public Ssortingng fileToSsortingng(File file, Charset charset) { Scanner fileReader = new Scanner(file, charset); fileReader.useDelimiter("\\Z"); // \Z means EOF. Ssortingng out = fileReader.next(); fileReader.close(); return out; } 

Si vous utilisez Java 7 ou une version plus récente (et vous devriez vraiment), envisagez d’utiliser try-with-resources pour rendre le code plus lisible. Plus de trucs à proximité de points qui jonchent tout. Mais c’est surtout un choix stylistique qui ne va pas.

Je publie ceci principalement pour des fins d’achèvement, car si vous devez le faire beaucoup, il devrait y avoir des choses dans java.nio.file.Files qui devraient mieux faire le travail.

Ma suggestion serait d’utiliser Files # readAllBytes (Path) pour récupérer tous les octets, et de le transmettre à new Ssortingng (byte [] Charset) pour en extraire une chaîne fiable. Les charsets seront méchants avec vous pendant votre vie, alors méfiez-vous de ces choses maintenant.

D’autres ont donné du code et des trucs, et je ne veux pas voler leur gloire. 😉

En utilisant cette bibliothèque , c’est une ligne:

 Ssortingng data = IO.from(new File("data.txt")).toSsortingng(); 

De plus, si votre fichier se trouve dans un fichier JAR, vous pouvez également utiliser ceci:

 public Ssortingng fromFileInJar(Ssortingng path) { try ( Scanner scanner = new Scanner(getClass().getResourceAsStream(path))) { return scanner.useDelimiter("\\A").next(); } } 

Le chemin doit commencer avec / par exemple si votre pot est

 my.jar/com/some/thing/a.txt 

Ensuite, vous voulez l’invoquer comme ceci:

 Ssortingng myTxt = fromFileInJar("/com/com/thing/a.txt"); 

En une ligne (Java 8), en supposant que vous ayez un lecteur:

 Ssortingng sMessage = Ssortingng.join("\n", reader.lines().collect(Collectors.toList())); 

Basé sur la réponse de @ erickson, vous pouvez utiliser:

 public Ssortingng readAll(Ssortingng fileName) throws IOException { List lines = Files.readAllLines(new File(fileName).toPath()); return Ssortingng.join("\n", lines.toArray(new Ssortingng[lines.size()])); } 

En utilisant JDK 8 ou supérieur:

aucune bibliothèque externe utilisée

Vous pouvez créer un nouvel object Ssortingng à partir du contenu du fichier (Utilisation des classes du package java.nio.file ):

 public Ssortingng readSsortingngFromFile(Ssortingng filePath) throws IOException { Ssortingng fileContent = new Ssortingng(Files.readAllBytes(Paths.get(filePath))); return fileContent; } 

Je ne peux pas encore commenter d’autres entrées, alors je vais juste le laisser ici.

Une des meilleures réponses ici ( https://stackoverflow.com/a/326448/1521167 ):

 private Ssortingng readFile(Ssortingng pathname) throws IOException { File file = new File(pathname); SsortingngBuilder fileContents = new SsortingngBuilder((int)file.length()); Scanner scanner = new Scanner(file); Ssortingng lineSeparator = System.getProperty("line.separator"); try { while(scanner.hasNextLine()) { fileContents.append(scanner.nextLine() + lineSeparator); } return fileContents.toSsortingng(); } finally { scanner.close(); } } 

a toujours un défaut. Il place toujours de nouveaux caractères de ligne à la fin de la chaîne, ce qui peut provoquer des bogues étranges. Ma suggestion est de la changer en:

  private Ssortingng readFile(Ssortingng pathname) throws IOException { File file = new File(pathname); SsortingngBuilder fileContents = new SsortingngBuilder((int) file.length()); Scanner scanner = new Scanner(new BufferedReader(new FileReader(file))); Ssortingng lineSeparator = System.getProperty("line.separator"); try { if (scanner.hasNextLine()) { fileContents.append(scanner.nextLine()); } while (scanner.hasNextLine()) { fileContents.append(lineSeparator + scanner.nextLine()); } return fileContents.toSsortingng(); } finally { scanner.close(); } } 

Use code:

 File file = new File("input.txt"); BufferedInputStream bin = new BufferedInputStream(new FileInputStream( file)); byte[] buffer = new byte[(int) file.length()]; bin.read(buffer); Ssortingng fileStr = new Ssortingng(buffer); 

fileStr contains output in Ssortingng.