Java: как читать текстовый файл

81

Я хочу прочитать текстовый файл, содержащий значения, разделенные пробелами. Значения целые. Как я могу прочитать его и поместить в список массивов?

Вот пример содержимого текстового файла:

1 62 4 55 5 6 77

Хочу в аррайлисте как [1, 62, 4, 55, 5, 6, 77]. Как это сделать на Java?

акс
источник

Ответы:

170

Вы можете использовать Files#readAllLines()для переноса всех строк текстового файла в List<String>.

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

Учебное пособие: Базовый ввод-вывод> Файловый ввод-вывод> Чтение, запись и создание текстовых файлов


Вы можете использовать String#split()для разделения на Stringчасти на основе регулярного выражения.

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

Учебное пособие: Числа и строки> Строки> Управление символами в строке


Вы можете использовать Integer#valueOf()для преобразования Stringв Integer.

Integer i = Integer.valueOf(part);

Учебное пособие: Числа и строки> Строки> Преобразование между числами и строками


Вы можете использовать, List#add()чтобы добавить элемент в List.

numbers.add(i);

Учебник: Интерфейсы> Интерфейс списка


Итак, в двух словах (при условии, что в файле нет пустых строк или конечных / ведущих пробелов).

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

Если вы уже знакомы с Java 8, вы даже можете использовать для этого Stream API , начиная с 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());

Учебник: Обработка данных с потоками Java 8

BalusC
источник
1
Обратите внимание, что в Java 7 и 8 есть более эффективные способы сделать это: stackoverflow.com/questions/4716503/…
Alex Beardsley
34

В Java 1.5 появился класс Scanner для обработки ввода из файла и потоков.

Он используется для получения целых чисел из файла и выглядит примерно так:

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

Однако проверьте API. Есть еще много вариантов работы с разными типами источников ввода, разными разделителями и разными типами данных.

tschaible
источник
2
это намного легче запомнить, чем комбинацию с буферизацией, io, reader
avanderw
18

В этом примере кода показано, как читать файл в 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

Посмотрите на этот пример и попробуйте сделать свой собственный:

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

Просто для удовольствия, вот что я, вероятно, сделал бы в реальном проекте, где я уже использую все свои любимые библиотеки (в данном случае Guava , ранее известный как 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));
}

Преимущество: не так много собственного кода, который нужно поддерживать (в отличие, например, от этого ). Изменить : хотя стоит отметить, что в этом случае решение сканера tschaible больше не имеет кода!

Недостаток: вы, очевидно, можете не захотеть добавлять новые зависимости библиотеки только для этого. (Опять же, было бы глупо не использовать Guava в своих проектах. ;-)

Йоник
источник
Конечно, можно также использовать transform () и функцию из Google Collections вместо цикла, но IMHO это было бы менее читабельно и даже не короче.
Джоник
4

Используйте Apache Commons (IO и Lang) для таких простых / обычных вещей.

Импорт:

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

Код:

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

Готово.

Крис
источник
2

Использование Java 7 для чтения файлов с помощью NIO.2

Импортируйте эти пакеты:

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

Это процесс чтения файла:

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

Чтобы прочитать сразу все строки файла:

Path file = Paths.get("C:\\Java\\file.txt");
List<String> lines = Files.readAllLines(file, StandardCharsets.UTF_8);
user2601995
источник
1

Все приведенные до сих пор ответы включают чтение файла построчно, ввод строки как a String, а затем обработку файла String.

Несомненно, это самый простой для понимания подход, и если файл достаточно короткий (скажем, десятки тысяч строк), он также будет приемлемым с точки зрения эффективности. Но если файл длинный , это очень неэффективный способ сделать это по двум причинам:

  1. Каждый символ обрабатывается дважды: один раз при построении Stringи один раз при обработке.
  2. Сборщик мусора не будет вашим другом, если в файле много строк. Вы создаете новый Stringдля каждой строки, а затем выбрасываете его, когда переходите к следующей строке. Сборщик мусора в конечном итоге должен будет избавиться от всех этих Stringобъектов, которые вам больше не нужны. Кто-то должен убирать за тобой.

Если вы заботитесь о скорости, вам гораздо лучше прочитать блок данных, а затем обработать его побайтно, а не построчно. Каждый раз, когда вы подходите к концу числа, вы добавляете его к Listсоздаваемому вами.

Получится примерно так:

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

В приведенном выше коде предполагается, что это ASCII (хотя его можно легко настроить для других кодировок), и что все, что не является цифрой (в частности, пробел или новая строка), представляет собой границу между цифрами. Он также предполагает, что файл заканчивается не цифрой (на практике последняя строка заканчивается новой строкой), хотя, опять же, его можно настроить, чтобы справиться со случаем, когда это не так.

Это намного, намного быстрее, чем любой из Stringподходов на основе, также приведенных в качестве ответов на этот вопрос. В этом вопросе есть подробное исследование очень похожей проблемы . Там вы увидите, что есть возможность улучшить его еще больше, если вы хотите перейти на многопоточную линию.

хиастическая безопасность
источник
0

прочтите файл, а затем сделайте все, что хотите. java8 Files.lines (Paths.get ("c: //lines.txt")). collect (Collectors.toList ());

Ран Адлер
источник