Java: Cách đọc tệp văn bản


81

Tôi muốn đọc một tệp văn bản chứa các giá trị được phân tách bằng dấu cách. Giá trị là số nguyên. Làm cách nào tôi có thể đọc nó và đưa nó vào danh sách mảng?

Đây là một ví dụ về nội dung của tệp văn bản:

1 62 4 55 5 6 77

Tôi muốn có nó trong một danh sách mảng như [1, 62, 4, 55, 5, 6, 77]. Làm thế nào tôi có thể làm điều đó trong Java?

Câu trả lời:


170

Bạn có thể sử dụng Files#readAllLines()để chuyển tất cả các dòng của tệp văn bản thành một List<String>.

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

Hướng dẫn: I / O cơ bản> I / O tệp> Đọc, ghi và tạo tệp văn bản


Bạn có thể sử dụng String#split()để chia một Stringphần dựa trên một biểu thức chính quy.

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

Hướng dẫn: Số và chuỗi> Chuỗi> Thao tác ký tự trong chuỗi


Bạn có thể sử dụng Integer#valueOf()để chuyển đổi một Stringthành một Integer.

Integer i = Integer.valueOf(part);

Hướng dẫn: Số và Chuỗi> Chuỗi> Chuyển đổi giữa Số và Chuỗi


Bạn có thể sử dụng List#add()để thêm một phần tử vào a List.

numbers.add(i);

Hướng dẫn: Giao diện> Giao diện danh sách


Vì vậy, tóm lại là (giả sử rằng tệp không có dòng trống hoặc khoảng trắng ở cuối / đầu).

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

Nếu bạn đã sử dụng Java 8 rồi, thì bạn thậm chí có thể sử dụng Stream API cho việc này, bắt đầu với 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());

Hướng dẫn: Xử lý dữ liệu với Java 8 luồng


1
Lưu ý rằng có những cách tốt hơn để làm điều này trong Java 7 và 8: stackoverflow.com/questions/4716503/...
Alex Beardsley

34

Java 1.5 đã giới thiệu lớp Máy quét để xử lý đầu vào từ tệp và luồng.

Nó được sử dụng để lấy số nguyên từ một tệp và sẽ trông giống như sau:

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

Kiểm tra API mặc dù. Có nhiều tùy chọn hơn để xử lý các loại nguồn đầu vào khác nhau, các dấu phân cách khác nhau và các kiểu dữ liệu khác nhau.


2
này là của xa dễ nhớ hơn so với đệm, io, kết hợp đọc
avanderw

18

Mã ví dụ này chỉ cho bạn cách đọc tệp trong Java.

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

Hãy xem ví dụ này và cố gắng làm theo cách của riêng bạ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

Nói cho vui, đây là những gì tôi có thể sẽ làm trong một dự án thực tế, nơi tôi đã sử dụng tất cả các thư viện yêu thích của mình (trong trường hợp này là Guava , trước đây được gọi là 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));
}

Lợi ích: Không có nhiều mã riêng để duy trì (tương phản với ví dụ: điều này ). Chỉnh sửa : Mặc dù cần lưu ý rằng trong trường hợp này , giải pháp Máy quét của tschaible không có thêm bất kỳ mã nào!

Hạn chế: rõ ràng là bạn có thể không muốn thêm các phụ thuộc thư viện mới chỉ cho việc này. (Một lần nữa, bạn thật ngớ ngẩn khi không sử dụng Ổi trong các dự án của mình. ;-)


Tất nhiên người ta cũng có thể sử dụng biến đổi () & một Hàm từ Bộ sưu tập của Google thay vì vòng lặp, nhưng IMHO sẽ khó đọc hơn và thậm chí không ngắn hơn.
Jonik

4

Sử dụng Apache Commons (IO và Lang) cho những việc đơn giản / phổ biến như thế này.

Nhập khẩu:

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

Mã:

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

Làm xong.


2

Sử dụng Java 7 để đọc tệp với NIO.2

Nhập các gói này:

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

Đây là quá trình để đọc một tệp:

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

Để đọc tất cả các dòng của tệp cùng một lúc:

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

1

Tất cả các câu trả lời cho đến nay đều liên quan đến việc đọc từng dòng của tệp, lấy dòng đó làm a String, và sau đó xử lý String.

Không nghi ngờ gì rằng đây là cách tiếp cận dễ hiểu nhất và nếu tệp khá ngắn (hàng chục nghìn dòng), nó cũng sẽ được chấp nhận về mặt hiệu quả. Nhưng nếu tệp dài , thì đó là một cách rất kém hiệu quả để làm điều đó, vì hai lý do:

  1. Mỗi ký tự được xử lý hai lần, một lần khi xây dựng Stringvà một lần khi xử lý nó.
  2. Trình thu gom rác sẽ không phải là bạn của bạn nếu có nhiều dòng trong tệp. Bạn đang tạo một cái mới Stringcho mỗi dòng, và sau đó vứt nó đi khi bạn chuyển sang dòng tiếp theo. Người thu gom rác cuối cùng sẽ phải vứt bỏ tất cả những Stringđồ vật mà bạn không muốn nữa. Ai đó phải dọn dẹp sau bạn.

Nếu bạn quan tâm đến tốc độ, bạn nên đọc một khối dữ liệu và sau đó xử lý nó theo từng byte thay vì từng dòng một. Mỗi khi bạn đến cuối một số, bạn thêm nó vào số Listbạn đang xây dựng.

Nó sẽ xuất hiện một cái gì đó như thế này:

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

Đoạn mã trên giả định rằng đây là ASCII (mặc dù nó có thể được điều chỉnh dễ dàng cho các mã hóa khác) và bất kỳ thứ gì không phải là chữ số (cụ thể là dấu cách hoặc dòng mới) đại diện cho ranh giới giữa các chữ số. Nó cũng giả định rằng tệp kết thúc bằng một chữ số không (trong thực tế, dòng cuối cùng kết thúc bằng một dòng mới), tuy nhiên, một lần nữa, nó có thể được điều chỉnh để đối phó với trường hợp không.

nhanh hơn nhiều so với bất kỳ Stringcách tiếp cận dựa trên cơ sở nào cũng được đưa ra như câu trả lời cho câu hỏi này. Có một cuộc điều tra chi tiết về một vấn đề rất giống trong câu hỏi này . Bạn sẽ thấy ở đó có khả năng cải thiện nó hơn nữa nếu bạn muốn đi xuống dòng đa luồng.


0

đọc tệp và sau đó làm bất cứ điều gì bạn muốn java8 Files.lines (Paths.get ("c: //lines.txt")). collect (Collectors.toList ());

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.