Lire un fichier texte en Java

Il semble qu’il existe différentes manières de lire et d’écrire des données de fichiers en Java.

Je veux lire les données ASCII d’un fichier. Quelles sont les voies possibles et leurs différences?

Ma manière préférée de lire un petit fichier est d’utiliser un BufferedReader et un SsortingngBuilder. C’est très simple et pertinent (mais pas particulièrement efficace, mais assez bon pour la plupart des cas):

 BufferedReader br = new BufferedReader(new FileReader("file.txt")); try { SsortingngBuilder sb = new SsortingngBuilder(); Ssortingng line = br.readLine(); while (line != null) { sb.append(line); sb.append(System.lineSeparator()); line = br.readLine(); } Ssortingng everything = sb.toSsortingng(); } finally { br.close(); } 

Certains ont souligné qu’après Java 7, vous devriez utiliser les fonctionnalités de try-with-resources (c. -à- d. Fermeture automatique):

 try(BufferedReader br = new BufferedReader(new FileReader("file.txt"))) { SsortingngBuilder sb = new SsortingngBuilder(); Ssortingng line = br.readLine(); while (line != null) { sb.append(line); sb.append(System.lineSeparator()); line = br.readLine(); } Ssortingng everything = sb.toSsortingng(); } 

Quand je lis des chaînes comme celle-ci, je veux en général manipuler des chaînes par ligne, alors je vais pour cette implémentation.

Bien que si je veux simplement lire un fichier dans une chaîne, j’utilise toujours Apache Commons IO avec la méthode de classe IOUtils.toSsortingng (). Vous pouvez consulter la source ici:

http://www.docjar.com/html/api/org/apache/commons/io/IOUtils.java.html

 FileInputStream inputStream = new FileInputStream("foo.txt"); try { Ssortingng everything = IOUtils.toSsortingng(inputStream); } finally { inputStream.close(); } 

Et encore plus simple avec Java 7:

 try(FileInputStream inputStream = new FileInputStream("foo.txt")) { Ssortingng everything = IOUtils.toSsortingng(inputStream); // do something with everything ssortingng } 

Le moyen le plus simple consiste à utiliser la classe Scanner dans Java et l’object FileReader. Exemple simple:

 Scanner in = new Scanner(new FileReader("filename.txt")); 

Scanner dispose de plusieurs méthodes pour lire des chaînes, des nombres, etc. Vous pouvez rechercher plus d’informations à ce sujet sur la page de documentation de Java.

Par exemple, lire tout le contenu dans une Ssortingng :

 SsortingngBuilder sb = new SsortingngBuilder(); while(in.hasNext()) { sb.append(in.next()); } in.close(); outSsortingng = sb.toSsortingng(); 

De plus, si vous avez besoin d’un encodage spécifique, vous pouvez l’utiliser à la place de FileReader :

 new InputStreamReader(new FileInputStream(fileUtf8), StandardCharsets.UTF_8) 

Voici une solution simple:

 Ssortingng content; content = new Ssortingng(Files.readAllBytes(Paths.get("sample.txt"))); 

Voici une autre façon de le faire sans utiliser de bibliothèques externes:

 import java.io.File; import java.io.FileReader; import java.io.IOException; public Ssortingng readFile(Ssortingng filename) { Ssortingng content = null; File file = new File(filename); // For example, foo.txt FileReader reader = null; try { reader = new FileReader(file); char[] chars = new char[(int) file.length()]; reader.read(chars); content = new Ssortingng(chars); reader.close(); } catch (IOException e) { e.printStackTrace(); } finally { if(reader != null){ reader.close(); } } return content; } 

J’ai dû évaluer les différentes manières. Je vais commenter mes découvertes mais, en bref, le moyen le plus rapide consiste à utiliser un vieux BufferedInputStream sur un FileInputStream. Si de nombreux fichiers doivent être lus, trois threads réduiront le temps d’exécution total à environ la moitié, mais l’ajout de nouveaux threads dégradera progressivement les performances jusqu’à ce qu’il faille trois fois plus de temps à compléter avec vingt threads.

L’hypothèse est que vous devez lire un fichier et faire quelque chose de significatif avec son contenu. Dans les exemples, nous lisons les lignes d’un journal et comptons celles qui contiennent des valeurs dépassant un certain seuil. Je suppose donc que le one-liner Java 8 Files.lines(Paths.get("/path/to/file.txt")).map(line -> line.split(";")) n’est pas une option .

J’ai testé sur Java 1.8, Windows 7 et les disques SSD et HDD.

J’ai écrit six implémentations différentes:

rawParse : utilisez BufferedInputStream sur un object FileInputStream, puis coupez les lignes en lisant octet par octet. Cela a surpassé toute autre approche à thread unique, mais cela peut être très gênant pour les fichiers non-ASCII.

lineReaderParse : utilisez un BufferedReader sur un FileReader, lisez ligne par ligne, séparez les lignes en appelant Ssortingng.split (). Ceci est approximativement 20% plus lent que rawParse.

lineReaderParseParallel : C’est la même chose que lineReaderParse, mais il utilise plusieurs threads. C’est l’option la plus rapide dans tous les cas.

nioFilesParse : Utilisez java.nio.files.Files.lines ()

nioAsyncParse : utilisez un AsynchronousFileChannel avec un gestionnaire d’achèvement et un pool de threads.

nioMemoryMappedParse : utilisez un fichier mappé en mémoire. C’est vraiment une mauvaise idée de générer des temps d’exécution au moins trois fois plus longs que toute autre implémentation.

Ce sont les durées moyennes de lecture de 204 fichiers de 4 Mo chacun sur un lecteur i7 et SSD à quatre cœurs. Les fichiers sont générés à la volée pour éviter la mise en cache des disques.

 rawParse 11.10 sec lineReaderParse 13.86 sec lineReaderParseParallel 6.00 sec nioFilesParse 13.52 sec nioAsyncParse 16.06 sec nioMemoryMappedParse 37.68 sec 

J’ai trouvé une différence plus petite que ce à quoi je m’attendais entre un disque SSD ou un disque dur dont le SSD était environ 15% plus rapide. Cela peut être dû au fait que les fichiers sont générés sur un disque dur non fragmenté et qu’ils sont lus séquentiellement. Par conséquent, le disque rotatif peut presque fonctionner comme un disque SSD.

J’ai été surpris par la faible performance de l’implémentation de nioAsyncParse. Soit j’ai implémenté quelque chose dans le mauvais sens, soit l’implémentation multi-thread à l’aide de NIO et un gestionnaire d’achèvement effectue la même chose (ou même pire) qu’une implémentation à thread unique avec l’API java.io. De plus, l’parsing asynchrone avec un CompletionHandler est beaucoup plus longue en lignes de code et difficile à implémenter correctement qu’une implémentation directe sur d’anciens stream.

Maintenant, les six implémentations suivies d’une classe les contenant toutes, plus une méthode principale paramétrable () qui permet de jouer avec le nombre de fichiers, la taille du fichier et le degré de concurrence. Notez que la taille des fichiers varie plus moins 20%. Ceci afin d’éviter tout effet dû au fait que tous les fichiers ont exactement la même taille.

rawParse

 public void rawParse(final Ssortingng targetDir, final int numberOfFiles) throws IOException, ParseException { overrunCount = 0; final int dl = (int) ';'; SsortingngBuffer lineBuffer = new SsortingngBuffer(1024); for (int f=0; f0) { switch (fieldNumber) { case 0: Date dt = fmt.parse(fieldValue); fieldNumber++; break; case 1: double d = Double.parseDouble(fieldValue); fieldNumber++; break; case 2: int t = Integer.parseInt(fieldValue); fieldNumber++; break; case 3: if (fieldValue.equals("overrun")) overrunCount++; break; } } fieldBuffer.setLength(0); } else { fieldBuffer.append(c); } } } 

lineReaderParse

 public void lineReaderParse(final Ssortingng targetDir, final int numberOfFiles) throws IOException, ParseException { Ssortingng line; for (int f=0; f 

lineReaderParseParallel

 public void lineReaderParseParallel(final Ssortingng targetDir, final int numberOfFiles, final int degreeOfParalelism) throws IOException, ParseException, InterruptedException { Thread[] pool = new Thread[degreeOfParalelism]; int batchSize = numberOfFiles / degreeOfParalelism; for (int b=0; b 

nioFilesParse

 public void nioFilesParse(final Ssortingng targetDir, final int numberOfFiles) throws IOException, ParseException { for (int f=0; f action = new LineConsumer(); Stream lines = Files.lines(ph); lines.forEach(action); lines.close(); } } class LineConsumer implements Consumer { @Override public void accept(Ssortingng line) { // What to do for each line Ssortingng[] fields = line.split(DL); if (fields.length>1) { try { Date dt = fmt.parse(fields[0]); } catch (ParseException e) { } double d = Double.parseDouble(fields[1]); int t = Integer.parseInt(fields[2]); if (fields[3].equals("overrun")) overrunCount++; } } } 

nioAsyncParse

 public void nioAsyncParse(final Ssortingng targetDir, final int numberOfFiles, final int numberOfThreads, final int bufferSize) throws IOException, ParseException, InterruptedException { ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(numberOfThreads); ConcurrentLinkedQueue byteBuffers = new ConcurrentLinkedQueue(); for (int b=0; b { private ConcurrentLinkedQueue buffers; private ByteBuffer bytes; private Ssortingng file; private SsortingngBuffer chars; private int limit; private long position; private DateFormat frmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public BufferConsumer(ConcurrentLinkedQueue byteBuffers, Ssortingng fileName, int bufferSize) { buffers = byteBuffers; bytes = buffers.poll(); if (bytes==null) bytes = ByteBuffer.allocate(bufferSize); file = fileName; chars = new SsortingngBuffer(bufferSize); frmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); limit = bufferSize; position = 0l; } public ByteBuffer buffer() { return bytes; } @Override public synchronized void completed(Integer result, AsynchronousFileChannel channel) { if (result!=-1) { bytes.flip(); final int len = bytes.limit(); int i = 0; try { for (i = 0; i < len; i++) { byte by = bytes.get(); if (by=='\n') { // *** // The code used to process the line goes here chars.setLength(0); } else { chars.append((char) by); } } } catch (Exception x) { System.out.println( "Caught exception " + x.getClass().getName() + " " + x.getMessage() + " i=" + String.valueOf(i) + ", limit=" + String.valueOf(len) + ", position="+String.valueOf(position)); } if (len==limit) { bytes.clear(); position += len; channel.read(bytes, position, channel, this); } else { try { channel.close(); } catch (IOException e) { } consumerThreads.release(); bytes.clear(); buffers.add(bytes); } } else { try { channel.close(); } catch (IOException e) { } consumerThreads.release(); bytes.clear(); buffers.add(bytes); } } @Override public void failed(Throwable e, AsynchronousFileChannel channel) { } }; 

MISE EN ŒUVRE COMPLETE DE TOUS LES CAS

https://github.com/sergiomt/javaiobenchmark/blob/master/FileReadBenchmark.java

Les méthodes dans org.apache.commons.io.FileUtils peuvent également être très utiles, par exemple:

 /** * Reads the contents of a file line by line to a List * of Ssortingngs using the default encoding for the VM. */ static List readLines(File file) 

Voici les trois méthodes de travail et testées:

Utiliser BufferedReader

 package io; import java.io.*; public class ReadFromFile2 { public static void main(Ssortingng[] args)throws Exception { File file = new File("C:\\Users\\pankaj\\Desktop\\test.java"); BufferedReader br = new BufferedReader(new FileReader(file)); Ssortingng st; while((st=br.readLine()) != null){ System.out.println(st); } } } 

Utilisation du Scanner

 package io; import java.io.File; import java.util.Scanner; public class ReadFromFileUsingScanner { public static void main(Ssortingng[] args) throws Exception { File file = new File("C:\\Users\\pankaj\\Desktop\\test.java"); Scanner sc = new Scanner(file); while(sc.hasNextLine()){ System.out.println(sc.nextLine()); } } } 

Utiliser FileReader

 package io; import java.io.*; public class ReadingFromFile { public static void main(Ssortingng[] args) throws Exception { FileReader fr = new FileReader("C:\\Users\\pankaj\\Desktop\\test.java"); int i; while ((i=fr.read()) != -1){ System.out.print((char) i); } } } 

Lire l’intégralité du fichier sans boucle à l’aide de la classe Scanner

 package io; import java.io.File; import java.io.FileNotFoundException; import java.util.Scanner; public class ReadingEntireFileWithoutLoop { public static void main(Ssortingng[] args) throws FileNotFoundException { File file = new File("C:\\Users\\pankaj\\Desktop\\test.java"); Scanner sc = new Scanner(file); sc.useDelimiter("\\Z"); System.out.println(sc.next()); } } 

Qu’est-ce que tu veux faire avec le texte? Le fichier est-il assez petit pour tenir en mémoire? Je voudrais essayer de trouver le moyen le plus simple de gérer le fichier pour vos besoins. La bibliothèque FileUtils est très pratique pour cela.

 for(Ssortingng line: FileUtils.readLines("my-text-file")) System.out.println(line); 

Vous trouverez ci-dessous un exemple de la manière de faire en Java 8. En supposant que le fichier text.txt trouve à la racine du répertoire du projet de l’Eclipse.

 Files.lines(Paths.get("text.txt")).collect(Collectors.toList()); 

Utilisation de BufferedReader:

 import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; BufferedReader br; try { br = new BufferedReader(new FileReader("/fileToRead.txt")); try { Ssortingng x; while ( (x = br.readLine()) != null ) { // Printing out each line in the file System.out.println(x); } } catch (IOException e) { e.printStackTrace(); } } catch (FileNotFoundException e) { System.out.println(e); e.printStackTrace(); } 

Ceci est fondamentalement la même que la réponse de Jesus Ramos, sauf avec File au lieu de FileReader plus itération pour parcourir le contenu du fichier.

 Scanner in = new Scanner(new File("filename.txt")); while (in.hasNext()) { // Iterates each line in the file Ssortingng line = in.nextLine(); // Do something with line } in.close(); // Don't forget to close resource leaks 

… lève FileNotFoundException

Probablement pas aussi rapide qu’avec les entrées / sorties en mémoire tampon, mais assez laconique:

  Ssortingng content; try (Scanner scanner = new Scanner(textFile).useDelimiter("\\Z")) { content = scanner.next(); } 

Le motif \Z indique au Scanner que le délimiteur est EOF.

J’ai documenté 15 façons de lire un fichier en Java , puis je les ai testées pour la vitesse avec différentes tailles de fichiers – de 1 Ko à 1 Go et voici les trois principales façons de procéder:

  1. java.nio.file.Files.readAllBytes()

    Testé pour fonctionner en Java 7, 8 et 9.

     import java.io.File; import java.io.IOException; import java.nio.file.Files; public class ReadFile_Files_ReadAllBytes { public static void main(Ssortingng [] pArgs) throws IOException { Ssortingng fileName = "c:\\temp\\sample-10KB.txt"; File file = new File(fileName); byte [] fileBytes = Files.readAllBytes(file.toPath()); char singleChar; for(byte b : fileBytes) { singleChar = (char) b; System.out.print(singleChar); } } } 
  2. java.io.BufferedReader.readLine()

    Testé pour travailler en Java 7, 8, 9.

     import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class ReadFile_BufferedReader_ReadLine { public static void main(Ssortingng [] args) throws IOException { Ssortingng fileName = "c:\\temp\\sample-10KB.txt"; FileReader fileReader = new FileReader(fileName); try (BufferedReader bufferedReader = new BufferedReader(fileReader)) { Ssortingng line; while((line = bufferedReader.readLine()) != null) { System.out.println(line); } } } } 
  3. java.nio.file.Files.lines()

    Cela a été testé pour fonctionner dans Java 8 et 9, mais ne fonctionnera pas dans Java 7 en raison de l’exigence de l’expression lambda.

     import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.util.stream.Stream; public class ReadFile_Files_Lines { public static void main(Ssortingng[] pArgs) throws IOException { Ssortingng fileName = "c:\\temp\\sample-10KB.txt"; File file = new File(fileName); try (Stream linesStream = Files.lines(file.toPath())) { linesStream.forEach(line -> { System.out.println(line); }); } } } 

Je ne le vois pas encore mentionné dans les autres réponses jusqu’à présent. Mais si “Best” signifie rapidité, la nouvelle E / S Java (NIO) peut fournir la performance la plus rapide, mais pas toujours la plus facile à comprendre pour quelqu’un.

http://download.oracle.com/javase/tutorial/essential/io/file.html

Le moyen le plus simple de lire les données d’un fichier en Java consiste à utiliser la classe File pour lire le fichier et la classe Scanner pour lire le contenu du fichier.

 public static void main(Ssortingng args[])throws Exception { File f = new File("input.txt"); takeInputIn2DArray(f); } public static void takeInputIn2DArray(File f) throws Exception { Scanner s = new Scanner(f); int a[][] = new int[20][20]; for(int i=0; i<20; i++) { for(int j=0; j<20; j++) { a[i][j] = s.nextInt(); } } } 

PS: N'oubliez pas d'importer java.util. *; pour que le scanner fonctionne.

Cela pourrait ne pas être la réponse exacte à la question. C’est juste une autre façon de lire un fichier où vous ne spécifiez pas explicitement le chemin d’access à votre fichier dans votre code Java et, à la place, vous le lisez comme un argument de ligne de commande.

Avec le code suivant,

 import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; public class InputReader{ public static void main(Ssortingng[] args)throws IOException{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); Ssortingng s=""; while((s=br.readLine())!=null){ System.out.println(s); } } } 

allez-y et lancez-le avec:

 java InputReader < input.txt 

Cela permettrait de lire le contenu du input.txt et de l’imprimer sur votre console.

Vous pouvez également rendre votre System.out.println() pour écrire dans un fichier spécifique via la ligne de commande comme suit:

 java InputReader < input.txt > output.txt 

Ceci lirait à partir de input.txt et écrirait à output.txt .

Pour les applications Web Maven basées sur JSF, utilisez simplement ClassLoader et le dossier Resources pour lire tout fichier souhaité:

  1. Placez tout fichier que vous souhaitez lire dans le dossier Resources.
  2. Mettez la dépendance Apache Commons IO dans votre POM:

      org.apache.commons commons-io 1.3.2  
  3. Utilisez le code ci-dessous pour le lire (par exemple, vous lisez ci-dessous un fichier .json):

     Ssortingng metadata = null; FileInputStream inputStream; try { ClassLoader loader = Thread.currentThread().getContextClassLoader(); inputStream = (FileInputStream) loader .getResourceAsStream("/metadata.json"); metadata = IOUtils.toSsortingng(inputStream); inputStream.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return metadata; 

Vous pouvez faire la même chose pour les fichiers texte, les fichiers .properties, les schémas XSD , etc.

Guava fournit un one-liner pour cela:

 import com.google.common.base.Charsets; import com.google.common.io.Files; Ssortingng contents = Files.toSsortingng(filePath, Charsets.UTF_8); 

Les cactos vous donnent un one-liner déclaratif:

 new TextOf(new File("a.txt")).asSsortingng(); 

Vous pouvez utiliser readAllLines et la méthode join pour obtenir un contenu de fichier complet sur une seule ligne:

 Ssortingng str = Ssortingng.join("\n",Files.readAllLines(Paths.get("e:\\text.txt"))); 

Il utilise le codage UTF-8 par défaut, qui lit correctement les données ASCII.

Vous pouvez également utiliser readAllBytes:

 Ssortingng str = new Ssortingng(Files.readAllBytes(Paths.get("e:\\text.txt")), StandardCharsets.UTF_8); 

Je pense que readAllBytes est plus rapide et plus précis, car il ne remplace pas la nouvelle ligne par \n et une nouvelle ligne peut aussi être \r\n . Cela dépend de vos besoins, celui qui convient.

Utilisez Java kiss si cela concerne la simplicité de la structure:

 import static kiss.API.*; class App { void run() { Ssortingng line; try (Close in = inOpen("file.dat")) { while ((line = readLine()) != null) { println(line); } } } } 

Ce code que j’ai programmé est beaucoup plus rapide pour les fichiers très volumineux:

 public Ssortingng readDoc(File f) { Ssortingng text = ""; int read, N = 1024 * 1024; char[] buffer = new char[N]; try { FileReader fr = new FileReader(f); BufferedReader br = new BufferedReader(fr); while(true) { read = br.read(buffer, 0, N); text += new Ssortingng(buffer, 0, read); if(read < N) { break; } } } catch(Exception ex) { ex.printStackTrace(); } return text; }