Java: Wie man eine Textdatei liest

81

Ich möchte eine Textdatei lesen, die durch Leerzeichen getrennte Werte enthält. Werte sind ganze Zahlen. Wie kann ich es lesen und in eine Array-Liste aufnehmen?

Hier ist ein Beispiel für den Inhalt der Textdatei:

1 62 4 55 5 6 77

Ich möchte es in einer Arrayliste haben als [1, 62, 4, 55, 5, 6, 77]. Wie kann ich das in Java machen?

aks
quelle

Antworten:

170

Sie können verwenden Files#readAllLines(), um alle Zeilen einer Textdatei in eine zu bekommen List<String>.

for (String line : Files.readAllLines(Paths.get("/path/to/file.txt"))) {
    // ...
}

Tutorial: Grundlegende E / A> Datei-E / A> Lesen, Schreiben und Erstellen von Textdateien


Sie können String#split()a Stringin Teile aufteilen, die auf einem regulären Ausdruck basieren.

for (String part : line.split("\\s+")) {
    // ...
}

Tutorial: Zahlen und Zeichenfolgen> Zeichenfolgen> Bearbeiten von Zeichen in einer Zeichenfolge


Sie können Integer#valueOf()ein Stringin ein konvertieren Integer.

Integer i = Integer.valueOf(part);

Tutorial: Zahlen und Zeichenfolgen> Zeichenfolgen> Konvertieren zwischen Zahlen und Zeichenfolgen


Sie können List#add()ein Element zu einem hinzufügen List.

numbers.add(i);

Tutorial: Schnittstellen> Die Listenschnittstelle


Kurz gesagt (vorausgesetzt, die Datei enthält weder Leerzeilen noch nachgestellte / führende Leerzeichen).

List<Integer> numbers = new ArrayList<>();
for (String line : Files.readAllLines(Paths.get("/path/to/file.txt"))) {
    for (String part : line.split("\\s+")) {
        Integer i = Integer.valueOf(part);
        numbers.add(i);
    }
}

Wenn Sie in Java 8 bereits geschehen sein, dann kann man auch verwenden Stream - API für diese, beginnend mit Files#lines().

List<Integer> numbers = Files.lines(Paths.get("/path/to/test.txt"))
    .map(line -> line.split("\\s+")).flatMap(Arrays::stream)
    .map(Integer::valueOf)
    .collect(Collectors.toList());

Tutorial: Verarbeiten von Daten mit Java 8-Streams

BalusC
quelle
1
Beachten Sie, dass es in Java 7 und 8 bessere Möglichkeiten gibt: stackoverflow.com/questions/4716503/…
Alex Beardsley
34

In Java 1.5 wurde die Scanner- Klasse für die Verarbeitung von Eingaben aus Dateien und Streams eingeführt.

Es wird zum Abrufen von Ganzzahlen aus einer Datei verwendet und sieht ungefähr so ​​aus:

List<Integer> integers = new ArrayList<Integer>();
Scanner fileScanner = new Scanner(new File("c:\\file.txt"));
while (fileScanner.hasNextInt()){
   integers.add(fileScanner.nextInt());
}

Überprüfen Sie jedoch die API. Es gibt viel mehr Optionen für den Umgang mit verschiedenen Arten von Eingabequellen, unterschiedlichen Trennzeichen und unterschiedlichen Datentypen.

tschaible
quelle
2
Dies ist bei weitem einfacher zu merken als die gepufferte, io, Leserkombination
avanderw
18

Dieser Beispielcode zeigt Ihnen, wie Sie Dateien in Java lesen.

import java.io.*;

/**
 * This example code shows you how to read file in Java
 *
 * IN MY CASE RAILWAY IS MY TEXT FILE WHICH I WANT TO DISPLAY YOU CHANGE WITH YOUR   OWN      
 */

 public class ReadFileExample 
 {
    public static void main(String[] args) 
    {
       System.out.println("Reading File from Java code");
       //Name of the file
       String fileName="RAILWAY.txt";
       try{

          //Create object of FileReader
          FileReader inputFile = new FileReader(fileName);

          //Instantiate the BufferedReader Class
          BufferedReader bufferReader = new BufferedReader(inputFile);

          //Variable to hold the one line data
          String line;

          // Read file line by line and print on the console
          while ((line = bufferReader.readLine()) != null)   {
            System.out.println(line);
          }
          //Close the buffer reader
          bufferReader.close();
       }catch(Exception e){
          System.out.println("Error while reading file line by line:" + e.getMessage());                      
       }

     }
  }
Sajjad Khan
quelle
10

Schauen Sie sich dieses Beispiel an und versuchen Sie, Ihr eigenes zu machen:

import java.io.*;

public class ReadFile {

    public static void main(String[] args){
        String string = "";
        String file = "textFile.txt";

        // Reading
        try{
            InputStream ips = new FileInputStream(file);
            InputStreamReader ipsr = new InputStreamReader(ips);
            BufferedReader br = new BufferedReader(ipsr);
            String line;
            while ((line = br.readLine()) != null){
                System.out.println(line);
                string += line + "\n";
            }
            br.close();
        }
        catch (Exception e){
            System.out.println(e.toString());
        }

        // Writing
        try {
            FileWriter fw = new FileWriter (file);
            BufferedWriter bw = new BufferedWriter (fw);
            PrintWriter fileOut = new PrintWriter (bw);
                fileOut.println (string+"\n test of read and write !!");
            fileOut.close();
            System.out.println("the file " + file + " is created!");
        }
        catch (Exception e){
            System.out.println(e.toString());
        }
    }
}
Eddinho
quelle
5

Nur zum Spaß, hier ist, was ich wahrscheinlich in einem echten Projekt tun würde, in dem ich bereits alle meine Lieblingsbibliotheken verwende (in diesem Fall Guava , früher bekannt als Google Collections ).

String text = Files.toString(new File("textfile.txt"), Charsets.UTF_8);
List<Integer> list = Lists.newArrayList();
for (String s : text.split("\\s")) {
    list.add(Integer.valueOf(s));
}

Vorteil: Nicht viel eigener Code zu erhalten (Gegensatz zu zB diesen ). Bearbeiten : Obwohl es erwähnenswert ist, dass in diesem Fall die Scanner-Lösung von tschaible keinen Code mehr enthält!

Nachteil: Möglicherweise möchten Sie nicht nur dafür neue Bibliotheksabhängigkeiten hinzufügen. (Andererseits wäre es dumm, Guava in Ihren Projekten nicht zu verwenden. ;-)

Jonik
quelle
Natürlich könnte man auch transform () & eine Funktion aus Google Collections anstelle der Schleife verwenden, aber meiner Meinung nach wäre das weniger lesbar und nicht einmal kürzer.
Jonik
4

Verwenden Sie Apache Commons (IO und Lang) für einfache / allgemeine Dinge wie diese.

Importe:

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ArrayUtils;

Code:

String contents = FileUtils.readFileToString(new File("path/to/your/file.txt"));
String[] array = ArrayUtils.toArray(contents.split(" "));

Getan.

Chris
quelle
2

Verwenden von Java 7 zum Lesen von Dateien mit NIO.2

Importieren Sie diese Pakete:

import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

Dies ist der Vorgang zum Lesen einer Datei:

Path file = Paths.get("C:\\Java\\file.txt");

if(Files.exists(file) && Files.isReadable(file)) {

    try {
        // File reader
        BufferedReader reader = Files.newBufferedReader(file, Charset.defaultCharset());

        String line;
        // read each line
        while((line = reader.readLine()) != null) {
            System.out.println(line);
            // tokenize each number
            StringTokenizer tokenizer = new StringTokenizer(line, " ");
            while (tokenizer.hasMoreElements()) {
                // parse each integer in file
                int element = Integer.parseInt(tokenizer.nextToken());
            }
        }
        reader.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

So lesen Sie alle Zeilen einer Datei gleichzeitig:

Path file = Paths.get("C:\\Java\\file.txt");
List<String> lines = Files.readAllLines(file, StandardCharsets.UTF_8);
user2601995
quelle
1

Alle bisher gegebenen Antworten beinhalten das zeilenweise Lesen der Datei, das Aufnehmen der Zeile als Stringund das anschließende Verarbeiten der String.

Es steht außer Frage, dass dies der am einfachsten zu verstehende Ansatz ist. Wenn die Datei ziemlich kurz ist (z. B. Zehntausende von Zeilen), ist sie auch im Hinblick auf die Effizienz akzeptabel. Wenn die Datei jedoch lang ist , ist dies aus zwei Gründen eine sehr ineffiziente Methode:

  1. Jedes Zeichen wird zweimal verarbeitet, einmal beim Erstellen des Stringund einmal beim Verarbeiten.
  2. Der Garbage Collector ist nicht Ihr Freund, wenn die Datei viele Zeilen enthält. Sie erstellen Stringfür jede Zeile eine neue und werfen sie dann weg, wenn Sie zur nächsten Zeile wechseln. Der Garbage Collector muss schließlich alle diese StringObjekte entsorgen , die Sie nicht mehr benötigen. Jemand muss nach dir aufräumen.

Wenn Sie Wert auf Geschwindigkeit legen, ist es viel besser, einen Datenblock zu lesen und ihn dann byteweise zu verarbeiten, als zeilenweise. Jedes Mal , wenn Sie an das Ende einer Reihe kommen, fügen Sie es auf die ListSie bauen.

Es wird ungefähr so ​​herauskommen:

private List<Integer> readIntegers(File file) throws IOException {
    List<Integer> result = new ArrayList<>();
    RandomAccessFile raf = new RandomAccessFile(file, "r");
    byte buf[] = new byte[16 * 1024];
    final FileChannel ch = raf.getChannel();
    int fileLength = (int) ch.size();
    final MappedByteBuffer mb = ch.map(FileChannel.MapMode.READ_ONLY, 0,
            fileLength);
    int acc = 0;
    while (mb.hasRemaining()) {
        int len = Math.min(mb.remaining(), buf.length);
        mb.get(buf, 0, len);
        for (int i = 0; i < len; i++)
            if ((buf[i] >= 48) && (buf[i] <= 57))
                acc = acc * 10 + buf[i] - 48;
            else {
                result.add(acc);
                acc = 0;
            }
    }
    ch.close();
    raf.close();
    return result;
}

Der obige Code geht davon aus, dass dies ASCII ist (obwohl es für andere Codierungen leicht angepasst werden kann) und dass alles, was keine Ziffer ist (insbesondere ein Leerzeichen oder eine neue Zeile), eine Grenze zwischen Ziffern darstellt. Es wird auch davon ausgegangen, dass die Datei mit einer Nicht-Ziffer endet (in der Praxis endet die letzte Zeile mit einer neuen Zeile). Sie kann jedoch erneut angepasst werden, um den Fall zu behandeln, in dem dies nicht der Fall ist.

Es ist viel, viel schneller als jeder der Stringbasierten Ansätze, die auch als Antwort auf diese Frage gegeben werden. Es gibt eine detaillierte Untersuchung eines sehr ähnlichen Themas in dieser Frage . Sie werden dort sehen, dass es die Möglichkeit gibt, es noch weiter zu verbessern, wenn Sie die Multithread-Linie durchlaufen möchten.

Chiastic-Sicherheit
quelle
0

Lesen Sie die Datei und machen Sie dann, was Sie wollen. java8 Files.lines (Paths.get ("c: //lines.txt")). collect (Collectors.toList ());

Ran Adler
quelle