Читать весь текст из файла
Вот компактная и надежная идиома для Java 7, заключенная в служебный метод:
static String readFile(String path, Charset encoding)
throws IOException
{
byte[] encoded = Files.readAllBytes(Paths.get(path));
return new String(encoded, encoding);
}
Чтение строк текста из файла
В Java 7 добавлен удобный метод для чтения файла в виде строк текста, представлен как List<String>
. Этот подход «с потерями», потому что разделители строк удаляются с конца каждой строки.
List<String> lines = Files.readAllLines(Paths.get(path), encoding);
Java 8 добавил метод Files.lines()
для получения Stream<String>
. Опять же, этот метод с потерями, потому что разделители строк удалены. Если при чтении файла встречается IOException
, он помещается в UncheckedIOException
, поскольку Stream
не принимает лямбда-выражения, которые выдают проверенные исключения.
try (Stream<String> lines = Files.lines(path, encoding)) {
lines.forEach(System.out::println);
}
Для этого Stream
требуется close()
вызов; это плохо документировано в API, и я подозреваю, что многие люди даже не замечают, что Stream
имеет метод close()
. Обязательно используйте ARM-блок, как показано на рисунке.
Если вы работаете с источником, отличным от файла, вы можете использовать метод lines()
в BufferedReader
.
Использование памяти
Первый метод, который сохраняет разрывы строк, может временно требовать памяти в несколько раз больше размера файла, потому что в течение короткого времени сырое содержимое файла (байтовый массив) и декодированные символы (каждый из которых составляет 16 битов) даже если он закодирован в файле как 8 битов), одновременно находятся в памяти. Безопаснее всего применять файлы, которые, как вы знаете, имеют небольшой размер относительно доступной памяти.
Второй метод, чтение строк, как правило, более эффективен для использования памяти, поскольку входной буфер байтов для декодирования не должен содержать весь файл. Тем не менее, он по-прежнему не подходит для файлов, которые имеют очень большой размер относительно доступной памяти.
Для чтения больших файлов вам понадобится другой дизайн вашей программы, который читает фрагмент текста из потока, обрабатывает его, а затем переходит к следующему, повторно используя тот же блок памяти фиксированного размера. Здесь «большой» зависит от технических характеристик компьютера. В настоящее время этот порог может составлять много гигабайт оперативной памяти. Третий метод, использующий Stream<String>
, является одним из способов сделать это, если ваши входные «записи» оказываются отдельными строками. (Использование readLine()
метода BufferedReader
является процедурным эквивалентом этого подхода.)
Кодировка символов
Единственное, чего не хватает в примере исходного сообщения, является кодировка символов. В некоторых особых случаях платформа по умолчанию - это то, что вам нужно, но они редки, и вы должны иметь возможность обосновать свой выбор.
Класс StandardCharsets
определяет некоторые константы для кодировок, требуемых для всех сред выполнения Java:
String content = readFile("test.txt", StandardCharsets.UTF_8);
Платформа по умолчанию доступна из самого Charset
класса :
String content = readFile("test.txt", Charset.defaultCharset());
Примечание. Этот ответ в значительной степени заменяет мою версию Java 6. Утилита Java 7 безопасно упрощает код, а старый ответ, в котором используется сопоставленный байтовый буфер, предотвращает удаление прочитанного файла до тех пор, пока сопоставленный буфер не будет очищен от мусора. Вы можете просмотреть старую версию по ссылке «отредактировано» в этом ответе.