Java: Bir metin dosyası nasıl okunur


81

Boşluklarla ayrılmış değerler içeren bir metin dosyası okumak istiyorum. Değerler tam sayılardır. Nasıl okuyabilirim ve bir dizi listesine koyabilirim?

Metin dosyasının içeriğinin bir örneği:

1 62 4 55 5 6 77

Bir dizi listesinde olmasını istiyorum [1, 62, 4, 55, 5, 6, 77]. Java'da nasıl yapabilirim?

Yanıtlar:


170

Sen kullanabilirsiniz Files#readAllLines()bir içine bir metin dosyasının tüm satırları almak için List<String>.

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

Eğitim: Temel G / Ç> Dosya G / Ç> Metin dosyalarını Okuma, Yazma ve Oluşturma


Bir normal ifadeye göre parçalara String#split()ayırmak için kullanabilirsiniz String.

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

Eğitim: Sayılar ve Dizeler> Dizeler> Bir Dizedeki Karakterleri Düzenleme


Sen kullanabilirsiniz Integer#valueOf()bir dönüştürmek için Stringbir içine Integer.

Integer i = Integer.valueOf(part);

Eğitim: Sayılar ve Dizeler> Dizeler> Sayılar ve Dizeler Arasında Dönüştürme


List#add()Bir öğesine bir öğe eklemek için kullanabilirsiniz List.

numbers.add(i);

Eğitim: Arayüzler> Liste Arayüzü


Yani, kısaca (dosyanın boş satırları veya sonunda / başında boşluk olmadığı varsayılarak).

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);
    }
}

Zaten Java 8'de olmak olur, o zaman bile kullanabilirsiniz Akış API ile başlayan Bunun için 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());

Eğitim: Java 8 akışlarıyla verileri işleme


1
Bunu Java 7 ve 8'de yapmanın daha iyi yolları olduğunu unutmayın: stackoverflow.com/questions/4716503/…
Alex Beardsley

34

Java 1.5 , dosya ve akışlardan gelen girdileri işlemek için Tarayıcı sınıfını tanıttı .

Bir dosyadan tamsayı almak için kullanılır ve şuna benzer:

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

Yine de API'yi kontrol edin. Farklı giriş kaynakları, farklı sınırlayıcılar ve farklı veri türleri ile uğraşmak için daha birçok seçenek vardır.


2
bunu hatırlamak, ara
belleğe

18

Bu örnek kod, Java'da dosyayı nasıl okuyacağınızı gösterir.

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());                      
       }

     }
  }

10

Bu örneğe bakın ve kendinizinkini yapmaya çalışın:

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());
        }
    }
}

5

Sırf eğlenmek için, işte zaten tüm favori kitaplıklarımı kullandığım gerçek bir projede muhtemelen yapacağım şey (bu durumda Guava , daha önce Google Koleksiyonları olarak biliniyordu ).

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));
}

Yarar: Koruması gereken çok fazla kod yok (örneğin bunun tersi ).Düzenleme : Bu durumda tschaible'ın Tarayıcı çözümünün daha fazla koda sahip olmadığını belirtmek gerekir!

Dezavantaj: Açıkçası, sadece bunun için yeni kütüphane bağımlılıkları eklemek istemeyebilirsiniz. (Sonra yine, Guava'yı projelerinizde kullanmamanız aptalca olur. ;-)


Elbette döngü yerine transform () ve Google Koleksiyonlarından bir İşlev kullanılabilir, ancak IMHO daha az okunabilir ve hatta daha kısa olamaz.
Jonik

4

Bunun gibi basit / yaygın şeyler için Apache Commons (IO ve Lang) kullanın .

İthalat:

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

Kod:

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

Bitti.


2

Dosyaları NIO.2 ile okumak için Java 7 kullanma

Bu paketleri içe aktarın:

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

Bu, bir dosyayı okuma işlemidir:

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();
    }
}

Bir dosyanın tüm satırlarını aynı anda okumak için:

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

1

Şimdiye kadar verilen tüm cevaplar, dosyayı satır satır okumak, satırı a olarak almak Stringve ardındanString .

Bunun anlaşılması en kolay yaklaşım olduğu konusunda hiçbir şüphe yok ve dosya oldukça kısaysa (örneğin on binlerce satır), verimlilik açısından da kabul edilebilir olacaktır. Ancak dosya uzunsa , bunu yapmanın iki nedenden dolayı çok verimsiz bir yoludur:

  1. Her karakter iki kez işlenir, bir kez String ve biri işlerken olmak .
  2. Dosyada çok sayıda satır varsa çöp toplayıcı arkadaşınız olmayacaktır. StringHer satır için yeni bir tane oluşturuyorsunuz ve bir sonraki satıra geçtiğinizde onu atıyorsunuz . Çöp toplayıcı eninde sonunda artık istemediğiniz tüm bu Stringnesneleri elden çıkarmak zorunda kalacaktır . Birinin arkanızı temizlemesi gerek.

Hızı önemsiyorsanız, bir veri bloğunu okumaktan ve onu satır satır yerine bayt olarak işlemekten çok daha iyi olursunuz. Bir sayının sonuna her geldiğinizde, onu oluşturduğunuz yere eklersiniz List.

Şöyle bir şey çıkacak:

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;
}

Yukarıdaki kod, bunun ASCII olduğunu (diğer kodlamalar için kolayca ayarlanabilse de) ve rakam olmayan herhangi bir şeyin (özellikle boşluk veya satırsonu) rakamlar arasındaki sınırı temsil ettiğini varsayar. Ayrıca, dosyanın rakamsız bir şekilde sona erdiğini varsayar (pratikte, son satır bir satırsonu ile biter), ancak yine de, olmadığı durumla başa çıkmak için ince ayar yapılabilir.

Bu var çok çok daha hızlı hepsinden daha Stringda bu soruya cevap olarak verilen tabanlı yaklaşımlar. Bu soruda çok benzer bir konunun detaylı bir araştırması var . Çok iş parçacıklı çizgiden aşağı inmek istiyorsanız, onu daha da geliştirme olasılığının olduğunu göreceksiniz.


0

dosyayı okuyun ve sonra istediğinizi yapın java8 Files.lines (Paths.get ("c: //lines.txt")). Collect (Collectors.toList ());

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.