Как создать строку Java из содержимого файла?

Я уже некоторое время использую идиому ниже. И он кажется самым распространенным, по крайней мере, на тех сайтах, которые я посещал.

Есть ли лучший / другой способ прочитать файл в строке в Java?

private String readFile(String file) throws IOException {
    BufferedReader reader = new BufferedReader(new FileReader (file));
    String         line = null;
    StringBuilder  stringBuilder = new StringBuilder();
    String         ls = System.getProperty("line.separator");

    try {
        while((line = reader.readLine()) != null) {
            stringBuilder.append(line);
            stringBuilder.append(ls);
        }

        return stringBuilder.toString();
    } finally {
        reader.close();
    }
}

Может ли кто-нибудь очень просто объяснить мне, что с NIO? Каждый раз, когда читаю об этом, я теряюсь в n-м упоминании канала :(

OscarRyz 28.11.2008 21:33

помните, что не гарантируется, что разделитель строк в файле не является таким же, как системный разделитель строк.

Henrik Paul 28.11.2008 21:35

В приведенном выше коде есть ошибка добавления дополнительного символа новой строки в последнюю строку. Это должно быть что-то вроде следующего if (line = reader.readLine ())! = Null) {stringBuilder.append (line); } пока (строка = reader.readLine ())! = ноль) {stringBuilder.append (ls); stringBuilder.append (строка); }

Deep 12.08.2011 14:29

Java 7 представляет byte[] Files.readAllBytes(file); Тем, кто предлагает решение «однострочного» сканера: не нужно ли его закрывать?

Val 17.01.2012 19:20

@OscarRyz Самым большим изменением для меня является то, что NIO позволяет вам прослушивать множество портов, не выделяя для каждого по потоку. Не проблема, если вы не хотите отправить пакет на каждую машину в сетевом адресном пространстве класса B (65 тыс. Адресов), чтобы увидеть, что существует, в Windows заканчиваются потоки примерно на 20 тыс. сеть класса A / B, до NIO было тяжело).

Bill K 17.03.2015 19:40

Если вы видите реализацию Files.readAllBytes (), вы заметите, что она использует закрываемый канал. Так что не нужно закрывать его явно.

Rajesh Goel 06.06.2017 02:41

С появлением Groovy вы можете читать файл таким образом: return new File (file) .text ()

Piko 02.08.2017 22:12

Связывание еще одной ссылки на StackOverflow, поиск которой хорошо объяснен: stackoverflow.com/questions/14169661/…

Love Bisaria 14.11.2017 04:26

@Deep Последняя строка в текстовом файле обычно заканчивается строкой, поэтому то, что вы описываете как ошибка, не является ошибкой, и в вашем коде есть ошибка удаления все ограничителей строки.

user207421 08.02.2019 02:37
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1 597
9
1 466 966
32

Ответы 32

Если вы хотите использовать внешнюю библиотеку, попробуйте Apache Commons IO (200 КБ JAR). Он содержит метод org.apache.commons.io.FileUtils.readFileToString(), который позволяет вам прочитать весь File в String с помощью одной строки кода.

Пример:

import java.io.*;
import java.nio.charset.*;
import org.apache.commons.io.*;

public String readFile() throws IOException {
    File file = new File("data.txt");
    return FileUtils.readFileToString(file, StandardCharsets.UTF_8);
}

Я не нахожу этого метода в указанном вами URL.

OscarRyz 28.11.2008 21:52

Это в классе org.apache.commons.io.FileUtils

Cyrille Ka 28.11.2008 22:04

Я тоже использую FileUtils, но мне интересно, что лучше между использованием FileUtils или принятым ответом nio?

Guillaume 09.02.2010 19:31

@Guillaume: Самый большой вопрос заключается в том, комфортно ли вам иметь зависимость от сторонней библиотеки. Если в вашем проекте есть Commons IO или Гуава, используйте их (просто для простоты кода; иначе, скорее всего, не будет заметной разницы).

Jonik 29.12.2013 17:04

Java пытается быть чрезвычайно универсальной и гибкой во всем, что она делает. В результате что-то, что относительно просто на языке сценариев (ваш код был бы заменен на «open(file).read()» в python), намного сложнее. Кажется, нет более короткого способа сделать это, кроме использования внешней библиотеки (например, упомянутой Вилли аус Рор). Ваши варианты:

  • Используйте внешнюю библиотеку.
  • Скопируйте этот код во все свои проекты.
  • Создайте свою собственную мини-библиотеку, содержащую часто используемые функции.

Лучше всего, вероятно, будет второй вариант, так как у него меньше всего зависимостей.

Ага. Это заставляет язык «высокого» уровня принимать другое значение. Java имеет высокий уровень по сравнению с C, но низкий по сравнению с Python или Ruby.

OscarRyz 28.11.2008 22:36

Согласитесь, что в Java много абстракций высокого уровня, но мало удобных методов.

Dónal 11.05.2011 20:44

Действительно, в Java есть безумное количество способов работы с файлами, и многие из них кажутся сложными. Но это довольно близко к тому, что мы имеем в языках более высокого уровня: byte[] bytes = Files.readAllBytes(someFile.toPath());

Thorn 17.04.2013 00:45

Прочитать весь текст из файла

В Java 11 добавлен метод readString () для чтения небольших файлов как String с сохранением терминаторов строк:

String content = Files.readString(path, StandardCharsets.US_ASCII);

Для версий между Java 7 и 11 вот компактная и надежная идиома, заключенная в служебный метод:

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 безопасно упрощает код, а старый ответ, в котором использовался сопоставленный байтовый буфер, предотвращал удаление файла, который был прочитан, до тех пор, пока сопоставленный буфер не будет собран сборщиком мусора. Вы можете просмотреть старую версию, перейдя по ссылке «отредактировано» в этом ответе.

Довольно интересно. Что означает канал. Я знаю, что это во избежание блокировки «нити»? Они могут быть двунаправленными (или я так понял) Но, проще говоря, что это такое? Не могли бы вы подробнее рассказать?

OscarRyz 28.11.2008 22:07

Во многих отношениях ReadableByteChannel похож на InputStream, а WritableByteChannel похож на OutputStream. Многие конкретные каналы реализуют оба этих интерфейса, поэтому один объект является двунаправленным. Некоторые каналы (SocketChannel) поддерживают неблокирующий ввод-вывод, но это верно не для всех каналов.

erickson 28.11.2008 22:11

Знаете ли вы, насколько эффективна эта идиома с точки зрения времени и памяти, или можете хотя бы оценить? Это красивая идиома!

Humphrey Bogart 18.06.2009 00:00

Технически говоря, это O (n) во времени и пространстве. Качественно, из-за требования неизменяемости строк, это довольно сложно для памяти; временно есть две копии данных char в памяти плюс место для закодированных байтов. Предполагая некоторую однобайтовую кодировку, потребуется (временно) 5 байтов памяти для каждого символа в файле. Поскольку вопрос конкретно касается String, это то, что я показываю, но если вы можете работать с CharBuffer, возвращаемым методом «decode», требования к памяти намного меньше. С точки зрения времени, я не думаю, что вы найдете что-то более быстрое в основных библиотеках Java.

erickson 18.06.2009 00:16

Возможная опечатка? У NIO есть класс Charset (не CharSet), называемый java.nio.charset.Charset. Это то, чем должен был быть CharSet?

Jonathan Wright 21.12.2009 01:43

Примечание: немного поработав этот код, я обнаружил, что вы не можете надежно удалить файл сразу после его прочтения с помощью этого метода, что в некоторых случаях может быть не проблемой, но не для меня. Может быть в связи с этим вопросом: bugs.sun.com/bugdatabase/view_bug.do?bug_id=4715154? В конце концов я согласился с предложением Джона Скита, который не страдает этой ошибкой. В любом случае, я просто хотел дать информацию другим людям, на всякий случай ...

Sébastien Nussbaumer 19.08.2010 19:47

@ Себастьен Нуссбаумер: Я тоже столкнулся с этой проблемой. Удивительно, что ошибка помечена как «Не исправить». По сути, это означает, что FileChannel#map вообще непригоден для использования.

Joonas Pulakka 09.11.2010 10:45

@ Себастьен Нуссбаумер: Ошибка была удалена из базы данных ошибок Oracle / Sun: «Эта ошибка недоступна». Google кэшировал сайт по адресу webcache.googleusercontent.com/search?q=cache:bugs.sun.com/…

bobndrew 01.08.2011 16:06

Я попытался прочитать exe-файл с помощью этого метода с кодировкой по умолчанию, добавить в него некоторые данные и снова сделать его exe, но он испортил exe, есть мысли?

foobar 13.09.2013 11:21

@smilepleeeaz То, что вы описываете, не имеет смысла. EXE-файлы не являются текстовыми. И у них есть четко определенная структура. Сначала вы уничтожаете содержимое файла, декодируя его как текст, затем вы разрушаете структуру, добавляя к ней текст. Как это могло не повредить EXE?

erickson 13.09.2013 19:20

Меня действительно не волнует кодировка, могу ли я просто использовать Charset.defaultCharset() вместо того, чтобы принимать аргумент?

corazza 12.01.2014 01:22

@yannbane Если вы уверены, что файл всегда будет кодироваться с использованием набора символов платформы по умолчанию, да, вы можете это сделать. Если есть несоответствие, вы позаботитесь о кодировке.

erickson 12.01.2014 03:25

Начиная с Java 8, кодировку можно не указывать по умолчанию для использования UTF-8. Таким образом, чтение всех строк становится Files.readAllLines(Paths.get("/your/path/to/file"));

Matthew Madson 27.03.2014 06:19

В чем преимущество этого: encoding.decode (ByteBuffer.wrap (закодировано)). ToString (); по сравнению с этим: новая строка (закодированная, кодировка);

Trejkaz 12.04.2014 03:33

@Trejkaz Нет ни одного! Я думаю, что это было просто перенесено из исходного кода, в котором использовался сопоставленный буфер. Спасибо, что указали на это.

erickson 12.04.2014 04:33

magnifico, решение java 8, а также

JohnMerlino 05.06.2014 00:21

В моем случае я делал это статическим методом, поэтому это выглядело так: URL url = NarrationDataProvider.class.getResource(filePath); byte[] encoded = Files.readAllBytes(Paths.get(url.toURI())); return new String(encoded, StandardCharsets.US_ASCII);

Philippe 30.07.2014 20:51

Применимо ли что-нибудь из этого к компиляторам?

CMCDragonkai 19.04.2015 11:20

Я попытался использовать метод readFile этого ответа, но не могу найти, где находится класс Files. Я использую JDK 1.7.0_79

Jpaji Rajnish 30.06.2015 03:24

@JpajiRajnish java.nio.file.Files

erickson 30.06.2015 03:25

К сожалению, этот фрагмент кода не работает в Android.

Miral Sarwar 24.08.2015 13:17

@MiralSarwar "не работает" - не совсем точное описание проблемы. Что случается? О каком из четырех фрагментов кода вы говорите?

erickson 24.08.2015 19:01

java.nio.file.Files или java.nio.file.Paths не поддерживаются в Android.

Miral Sarwar 25.08.2015 07:02

@MiralSarwar Ну, этот вопрос касается Java, а не Android, но версия Java 6 (которую можно просмотреть в истории редактирования) будет работать на Android.

erickson 25.08.2015 19:04

Раздел «Кодировка символов» должен быть закрыт теперь, когда вы удалили все другие ссылки на Apache Commons IO.

Powerlord 04.02.2016 18:22

@Powerlord Этот раздел не имеет ничего общего с Apache Commons IO. Это полностью относится к ядру Java NIO.

erickson 04.02.2016 19:37

Если вы ищете альтернативу, не использующую стороннюю библиотеку (например, Ввод / вывод общего пользования), вы можете использовать класс Сканер:

private String readFile(String pathname) throws IOException {

    File file = new File(pathname);
    StringBuilder fileContents = new StringBuilder((int)file.length());        

    try (Scanner scanner = new Scanner(file)) {
        while(scanner.hasNextLine()) {
            fileContents.append(scanner.nextLine() + System.lineSeparator());
        }
        return fileContents.toString();
    }
}

Думаю, это лучший способ. Проверить java.sun.com/docs/books/tutorial/essential/io/scanning.html

Tarski 28.11.2008 22:19

Конструктор Scanner, который принимает String, обрабатывает строку не как имя файла для чтения, а как текст для сканирования. Я все время делаю эту ошибку. : - /

Alan Moore 29.11.2008 12:10

@ Алан, хороший улов. Я немного отредактировал ответ Дона, чтобы исправить это (надеюсь).

Jonik 17.04.2010 14:12

fileContents.append (scanner.nextLine ()). append (lineSeparator‌);

ban-geoengineering 24.05.2013 14:53

Измените оператор инициализации на Scanner scanner = new Scanner((Readable) new BufferedReader(new FileReader(file)));. В противном случае вы можете захватить только часть файла.

Wei Yang 22.10.2013 21:40

Этот метод добавит дополнительный разделитель в конец файла, когда его нет в фактическом файле (для файла, который заканчивается без новой строки).

forumulator 10.08.2018 06:35

@WeiYang Почему?

golimar 24.10.2018 17:42

Этот код нормализует разрывы строк, что может быть, а может и не быть тем, что вы действительно хотите делать.

Вот альтернатива, которая этого не делает и которая (IMO) проще для понимания, чем код NIO (хотя он все еще использует java.nio.charset.Charset):

public static String readFile(String file, String csName)
            throws IOException {
    Charset cs = Charset.forName(csName);
    return readFile(file, cs);
}

public static String readFile(String file, Charset cs)
            throws IOException {
    // No real need to close the BufferedReader/InputStreamReader
    // as they're only wrapping the stream
    FileInputStream stream = new FileInputStream(file);
    try {
        Reader reader = new BufferedReader(new InputStreamReader(stream, cs));
        StringBuilder builder = new StringBuilder();
        char[] buffer = new char[8192];
        int read;
        while ((read = reader.read(buffer, 0, buffer.length)) > 0) {
            builder.append(buffer, 0, read);
        }
        return builder.toString();
    } finally {
        // Potential issue here: if this throws an IOException,
        // it will mask any others. Normally I'd use a utility
        // method which would log exceptions and swallow them
        stream.close();
    }        
}

Простите меня за то, что возродил такой старый комментарий, но вы хотели передать объект String с именем "file" или это должен быть объект File?

Bryan Larson 05.06.2013 23:17

Отличный ответ. +1. Но этому ответу 12 лет. В Java теперь есть возможность попробовать ресурсы.

Harshal Parekh 10.11.2020 23:32

Существует вариант той же темы, в которой вместо цикла while используется цикл for, чтобы ограничить область действия строковой переменной. «Лучше» ли это - дело личного вкуса.

for(String line = reader.readLine(); line != null; line = reader.readLine()) {
    stringBuilder.append(line);
    stringBuilder.append(ls);
}

Это изменит символы новой строки на выбор по умолчанию. Это может быть желательно или непреднамеренно.

Peter Lawrey 18.04.2010 11:23

Откатил редактирование этого ответа, потому что цель заключалась в том, чтобы сузить область действия переменной line. Редакция объявила это дважды, что было бы ошибкой компиляции.

Dan Dyer 02.08.2013 00:16
public static String slurp (final File file)
throws IOException {
    StringBuilder result = new StringBuilder();

    BufferedReader reader = new BufferedReader(new FileReader(file));

    try {
        char[] buf = new char[1024];

        int r = 0;

        while ((r = reader.read(buf)) != -1) {
            result.append(buf, 0, r);
        }
    }
    finally {
        reader.close();
    }

    return result.toString();
}

Я думаю, что это неудобно при использовании кодировки платформы по умолчанию. +1 все равно :)

OscarRyz 09.02.2010 18:53

Мне кажется, что блок finally не знает переменных, определенных в блоке try. javac 1.6.0_21 выдает ошибку cannot find symbol.

ceving 25.06.2012 20:11

Вы хоть раз пробовали свой собственный код? Вы определили читателя в блоке try / catch, поэтому он не будет доступен в блоке finally.

mauron85 31.10.2018 12:48

Гуава имеет метод, аналогичный методу из Commons IOUtils, который упомянул Вилли аус Рор:

import com.google.common.base.Charsets;
import com.google.common.io.Files;

// ...

String text = Files.toString(new File(path), Charsets.UTF_8);

ИЗМЕНИТЬ PiggyPiglet
Files#toString устарел и подлежит удалению в октябре 2019 года. Вместо этого используйте Files.asCharSource(new File(path), StandardCharsets.UTF_8).read();

РЕДАКТИРОВАТЬ Оскар Рейес

Это (упрощенный) базовый код указанной библиотеки:

InputStream in = new FileInputStream(file);
byte[] b  = new byte[file.length()];
int len = b.length;
int total = 0;

while (total < len) {
  int result = in.read(b, total, len - total);
  if (result == -1) {
    break;
  }
  total += result;
}

return new String( b , Charsets.UTF_8 );

Редактировать (от Jonik): приведенное выше не соответствует исходному коду последних версий Guava. Для текущего источника см. Классы Файлы, CharStreams, ByteSource и CharSource в пакете com.google.common.io.

Этот код имеет преобразование от long к int, что может вызвать сумасшедшее поведение с большими файлами. Есть лишние пробелы и где вы закрываете поток ввода?

Mohamed Taher Alrefaie 22.04.2013 19:42

@ M-T-A: поток является закрыт, обратите внимание на использование Closer в CharSource. Код в ответе не является фактическим текущим исходным кодом Guava.

Jonik 29.12.2013 17:19

Чтобы прочитать файл как двоичный и преобразовать в конце

public static String readFileAsString(String filePath) throws IOException {
    DataInputStream dis = new DataInputStream(new FileInputStream(filePath));
    try {
        long len = new File(filePath).length();
        if (len > Integer.MAX_VALUE) throw new IOException("File "+filePath+" too large, was "+len+" bytes.");
        byte[] bytes = new byte[(int) len];
        dis.readFully(bytes);
        return new String(bytes, "UTF-8");
    } finally {
        dis.close();
    }
}

Очень простое решение, основанное на Scanner:

Scanner scanner = new Scanner( new File("poem.txt") );
String text = scanner.useDelimiter("\\A").next();
scanner.close(); // Put this call in a finally block

Или, если вы хотите установить кодировку:

Scanner scanner = new Scanner( new File("poem.txt"), "UTF-8" );
String text = scanner.useDelimiter("\\A").next();
scanner.close(); // Put this call in a finally block

Или с блоком попробовать с ресурсами, который вызовет для вас scanner.close():

try (Scanner scanner = new Scanner( new File("poem.txt"), "UTF-8" )) {
    String text = scanner.useDelimiter("\\A").next();
}

Помните, что конструктор Scanner может выдавать IOException. И не забудьте импортировать java.io и java.util.

Источник: Блог Пэта Нимейера

\\ A работает, потому что нет "другого начала файла", поэтому вы фактически читаете последний токен ... который также является первым. Никогда не пробовал с \\ Z. Также обратите внимание, что вы можете читать все, что доступно для чтения, например, Files, InputStreams, каналы ... Иногда я использую этот код для чтения из окна отображения eclipse, когда я не уверен, читаю ли я тот или иной файл .. .да, путь к классам меня смущает.

Pablo Grisafi 17.09.2011 00:16

Как плакат, я могу сказать, что действительно не знаю, правильно ли закрыт файл и когда ... Я никогда не пишу его в производственном коде, я использую его только для тестов или отладки.

Pablo Grisafi 04.06.2012 21:26

Я думаю, он имеет ограничение в 1024 символа

Whimusical 04.07.2012 18:32

Сканер реализует Closeable (он вызывает close для источника), поэтому, хотя он элегантен, он не должен быть однострочным. Размер буфера по умолчанию - 1024, но Scanner при необходимости увеличит его размер (см. Scanner # makeSpace ())

earcam 23.11.2012 13:43

Этот не подходит для пустых файлов с java.util.NoSuchElementException.

SpaceTrucker 02.08.2013 13:16

Это решение позволяет читать файлы из потоков, поэтому вы можете читать, например, ресурсы пути к классам. Широко предлагаемое решение Files.readAllBytes(Paths.get(path)) не работает, например, в среде JEE.

Vladimir Sosnin 25.09.2015 22:20

Кроме того, не забудьте вызвать trim() в результирующей строке, если вы не хотите, чтобы \r\n был добавлен в конец.

shieldgenerator7 02.02.2016 20:16

@SpaceTrucker это можно исправить, используя sc.findWithinHorizon("(?s).*", 0) вместо .useDelimiter("\\A").next(). Затем он будет соответствовать всему (возможно, пустому) файлу вместо поиска разделителя.

Holger 13.09.2019 11:53

@VladimirSosnin зависит от типа ресурса classpath и доступных реализаций файловой системы. Для хранения файлов и модулей Files.readAllBytes(Paths.get(url.toURI())) работает "из коробки", тогда как для записей jar вам нужно будет создать ZipFileSystem один раз вручную в начале вашего приложения. Для других, специальных конструкций ваш контейнер должен предоставлять необходимую файловую систему, что действительно не гарантируется. Но начиная с Java 9, вы можете вызывать readAllBytes() прямо на InputStream.

Holger 13.09.2019 11:57

Если это текстовый файл, почему бы не использовать Apache Commons-io?

Он имеет следующий метод

public static String readFileToString(File file) throws IOException

Если вы хотите, чтобы строки в виде списка использовали

public static List<String> readLines(File file) throws IOException

Здесь используется метод RandomAccessFile.readFully, кажется, он доступен из JDK 1.0!

public static String readFileContent(String filename, Charset charset) throws IOException {
    RandomAccessFile raf = null;
    try {
        raf = new RandomAccessFile(filename, "r");
        byte[] buffer = new byte[(int)raf.length()];
        raf.readFully(buffer);
        return new String(buffer, charset);
    } finally {
        closeStream(raf);
    }
} 


private static void closeStream(Closeable c) {
    if (c != null) {
        try {
            c.close();
        } catch (IOException ex) {
            // do nothing
        }
    }
}

Гибкое решение с использованием IOUtils от Apache Commons-io в сочетании с StringWriter:

Reader input = new FileReader();
StringWriter output = new StringWriter();
try {
  IOUtils.copy(input, output);
} finally {
  input.close();
}
String fileContents = output.toString();

Он работает с любым считывателем или входным потоком (не только с файлами), например, при чтении с URL-адреса.

import java.nio.file.Files;

.......

 String readFile(String filename) {
            File f = new File(filename);
            try {
                byte[] bytes = Files.readAllBytes(f.toPath());
                return new String(bytes,"UTF-8");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return "";
    }

Или еще проще: new String(Files.readAllBytes(FileSystems.getDefault().getPath( filename)));

user321068 07.08.2012 01:54

или new String(Files.readAllBytes(Paths.get(filename))); :-)

assafmo 06.04.2013 16:09

Хорошо сыграно, и, чтобы спасти следующего парня из Google, Paths, по-видимому, 1.7+, как FileSystems. (Черт возьми!)

ruffin 09.04.2013 23:51

Жаль, что за этот ответ не набралось больше голосов. Я искал самый быстрый и простой способ превратить текстовый файл в строку. Вот и все, и если бы я не прокручивал вниз и вниз и вниз, я бы это пропустил. OP должен рассмотреть возможность принятия этого ответа, чтобы переместить его наверх.

Thorn 16.04.2013 08:40

@Thorn В этом ответе ужасная обработка ошибок. Не используйте этот метод в производственном коде, или лучше: никогда.

xehpuk 21.02.2015 02:35

Имейте в виду, что при использовании fileInputStream.available() возвращаемое целое число не должно представлять фактический размер файла, а скорее предполагаемое количество байтов, которое система должна иметь возможность читать из потока без блокировки ввода-вывода. Безопасный и простой способ может выглядеть так

public String readStringFromInputStream(FileInputStream fileInputStream) {
    StringBuffer stringBuffer = new StringBuffer();
    try {
        byte[] buffer;
        while (fileInputStream.available() > 0) {
            buffer = new byte[fileInputStream.available()];
            fileInputStream.read(buffer);
            stringBuffer.append(new String(buffer, "ISO-8859-1"));
        }
    } catch (FileNotFoundException e) {
    } catch (IOException e) { }
    return stringBuffer.toString();
}

Следует учитывать, что этот подход нет подходит для многобайтовых кодировок символов, таких как UTF-8.

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

wau 15.03.2013 17:32

Я пока не могу комментировать другие записи, поэтому оставлю это здесь.

Один из лучших ответов здесь (https://stackoverflow.com/a/326448/1521167):

private String readFile(String pathname) throws IOException {

File file = new File(pathname);
StringBuilder fileContents = new StringBuilder((int)file.length());
Scanner scanner = new Scanner(file);
String lineSeparator = System.getProperty("line.separator");

try {
    while(scanner.hasNextLine()) {        
        fileContents.append(scanner.nextLine() + lineSeparator);
    }
    return fileContents.toString();
} finally {
    scanner.close();
}
}

еще есть один недостаток. Он всегда помещает символ новой строки в конец строки, что может вызвать некоторые странные ошибки. Я предлагаю изменить его на:

    private String readFile(String pathname) throws IOException {
    File file = new File(pathname);
    StringBuilder fileContents = new StringBuilder((int) file.length());
    Scanner scanner = new Scanner(new BufferedReader(new FileReader(file)));
    String lineSeparator = System.getProperty("line.separator");

    try {
        if (scanner.hasNextLine()) {
            fileContents.append(scanner.nextLine());
        }
        while (scanner.hasNextLine()) {
            fileContents.append(lineSeparator + scanner.nextLine());
        }
        return fileContents.toString();
    } finally {
        scanner.close();
    }
}

В первом случае вы могли бы добавить в конец дополнительный перевод строки. во втором случае вы можете пропустить один. Так что оба одинаково неправы. См. эта статья

Patrick Parker 28.03.2018 16:46

Если вам нужна обработка строк (параллельная обработка), в Java 8 есть отличный Stream API.

String result = Files.lines(Paths.get("file.txt"))
                    .parallel() // for parallel processing 
                    .map(String::trim) // to change line   
                    .filter(line -> line.length() > 2) // to filter some lines by a predicate                        
                    .collect(Collectors.joining()); // to join lines

Дополнительные примеры доступны в образцах JDK sample/lambda/BulkDataOperations, которые можно загрузить с Страница загрузки Oracle Java SE 8.

Еще один пример лайнера

String out = String.join("\n", Files.readAllLines(Paths.get("file.txt")));

Выполняется ли .parallel () после того, как вы прочитаете строки или до этого?

Istvan 17.04.2015 23:17

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

Andrei N 21.04.2015 18:17

обрезать перед выбором непустых строк?

Thorbjørn Ravn Andersen 13.01.2016 22:16

Если у вас нет доступа к классу Files, вы можете использовать собственное решение.

static String readFile(File file, String charset)
        throws IOException
{
    FileInputStream fileInputStream = new FileInputStream(file);
    byte[] buffer = new byte[fileInputStream.available()];
    int length = fileInputStream.read(buffer);
    fileInputStream.close();
    return new String(buffer, 0, length, charset);
}

пример кодировки для вызова?

Thufir 30.12.2018 11:48

После нажатия Ctrl + F после Scanner, я думаю, что решение Scanner тоже должно быть указано. Проще всего это выглядит так:

public String fileToString(File file, Charset charset) {
  Scanner fileReader = new Scanner(file, charset);
  fileReader.useDelimiter("\\Z"); // \Z means EOF.
  String out = fileReader.next();
  fileReader.close();
  return out;
}

Если вы используете Java 7 или новее (а вам действительно стоит), подумайте об использовании try-with-resources, чтобы упростить чтение кода. Больше никаких беспорядков, засоряющих все вокруг. Но я думаю, это в основном стилистический выбор.

Я публикую это в основном для завершения, поскольку, если вам нужно делать это много, в java.nio.file.Files должны быть вещи, которые должны выполнять эту работу лучше.

Я предлагаю использовать Файлы # readAllBytes (Путь), чтобы захватить все байты и передать их новому Строка (byte [] Charset), чтобы получить из него строку, которой вы можете доверять. Кодировки будут иметь значение для вас в течение всей вашей жизни, так что остерегайтесь этого сейчас.

Другие дали код и прочее, и я не хочу украсть их славу. ;)

В Java 7 я предпочитаю читать файл UTF-8:

String content = new String(Files.readAllBytes(Paths.get(filename)), "UTF-8");

Начиная с Java 7, JDK имеет новый API java.nio.file, который предоставляет множество ярлыков, поэтому сторонние библиотеки не всегда требуются для простых операций с файлами.

import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;

String content = new String(Files.readAllBytes(Paths.get("readMe.txt")), StandardCharsets.UTF_8);

начиная с java 7 вы можете сделать это таким образом.

Это следует принять как ответ - одна строка, никаких внешних библиотек.

Cherry 04.05.2018 19:07

Это добавило символ новой строки в конце, даже если его не было в файле

Stefan Haberl 12.02.2020 17:38

в java 8 есть новый класс

java.util.stream.Stream

Поток представляет собой последовательность элементов и поддерживает различные типы операций для выполнения вычислений над этими элементами.

Подробнее об этом:

Документация Oracle

Вот пример:

import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;

public Class ReadFile{
  public  static String readFile(String filePath) {
 StringBuilder  stringBuilder = new StringBuilder();
    String ls = System.getProperty("line.separator");
        try {

            try (Stream<String> lines = Files.lines(Paths.get(filePath), StandardCharsets.UTF_8)) {
                for (String line : (Iterable<String>) lines::iterator) {


                      stringBuilder.append(line);
                      stringBuilder.append(ls);


                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

      return stringBuilder.toString(); 


}

}

Используя эта библиотека, это одна строка:

String data = IO.from(new File("data.txt")).toString();

если не учитываются строки внутри библиотеки.

Ari 01.08.2017 05:13

Используйте код:

File file = new File("input.txt");
BufferedInputStream bin = new BufferedInputStream(new FileInputStream(
                file));
byte[] buffer = new byte[(int) file.length()];
bin.read(buffer);
String fileStr = new String(buffer);

fileStr содержит вывод в виде строки.

Вы можете попробовать класс Scanner и File, решение из нескольких строк

 try
{
  String content = new Scanner(new File("file.txt")).useDelimiter("\\Z").next();
  System.out.println(content);
}
catch(FileNotFoundException e)
{
  System.out.println("not found!");
}

Также, если ваш файл находится внутри банки, вы также можете использовать это:

public String fromFileInJar(String path) {
    try ( Scanner scanner 
            = new Scanner(getClass().getResourceAsStream(path))) {
        return scanner.useDelimiter("\\A").next();
    }
}

Путь должен начинаться с /, например, если ваша банка

my.jar/com/some/thing/a.txt

Затем вы хотите вызвать его так:

String myTxt = fromFileInJar("/com/com/thing/a.txt");

В одной строке (Java 8), если у вас есть Reader:

String sMessage = String.join("\n", reader.lines().collect(Collectors.toList()));

Основываясь на ответе @ erickson, вы можете использовать:

public String readAll(String fileName) throws IOException {
    List<String> lines = Files.readAllLines(new File(fileName).toPath());
    return String.join("\n", lines.toArray(new String[lines.size()]));
}

Собрал все возможные способы чтения файла в виде строки с диска или сети.

  • Гуава: Google с использованием классов Resources, Files

    static Charset charset = com.google.common.base.Charsets.UTF_8;
    public static String guava_ServerFile( URL url ) throws IOException {
        return Resources.toString( url, charset );
    }
    public static String guava_DiskFile( File file ) throws IOException {
        return Files.toString( file, charset );
    }
    

  • APACHE - ОБЫЧНЫЙ IO с использованием классов IOUtils, FileUtils

    static Charset encoding = org.apache.commons.io.Charsets.UTF_8;
    public static String commons_IOUtils( URL url ) throws IOException {
        java.io.InputStream in = url.openStream();
        try {
            return IOUtils.toString( in, encoding );
        } finally {
            IOUtils.closeQuietly(in);
        }
    }
    public static String commons_FileUtils( File file ) throws IOException {
        return FileUtils.readFileToString( file, encoding );
        /*List<String> lines = FileUtils.readLines( fileName, encoding );
        return lines.stream().collect( Collectors.joining("\n") );*/
    }
    

  • Java 8 BufferReader с использованием Stream API

    public static String streamURL_Buffer( URL url ) throws IOException {
        java.io.InputStream source = url.openStream();
        BufferedReader reader = new BufferedReader( new InputStreamReader( source ) );
        //List<String> lines = reader.lines().collect( Collectors.toList() );
        return reader.lines().collect( Collectors.joining( System.lineSeparator() ) );
    }
    public static String streamFile_Buffer( File file ) throws IOException {
        BufferedReader reader = new BufferedReader( new FileReader( file ) );
        return reader.lines().collect(Collectors.joining(System.lineSeparator()));
    }
    

  • Класс сканера с регулярным выражением \A. что соответствует началу ввода.

    static String charsetName = java.nio.charset.StandardCharsets.UTF_8.toString();
    public static String streamURL_Scanner( URL url ) throws IOException {
        java.io.InputStream source = url.openStream();
        Scanner scanner = new Scanner(source, charsetName).useDelimiter("\\A");
        return scanner.hasNext() ? scanner.next() : "";
    }
    public static String streamFile_Scanner( File file ) throws IOException {
        Scanner scanner = new Scanner(file, charsetName).useDelimiter("\\A");
        return scanner.hasNext() ? scanner.next() : "";
    }
    

  • Java 7 (java.nio.file.Files.readAllBytes)

    public static String getDiskFile_Java7( File file ) throws IOException {
        byte[] readAllBytes = java.nio.file.Files.readAllBytes(Paths.get( file.getAbsolutePath() ));
        return new String( readAllBytes );
    }
    

  • BufferedReader с использованием InputStreamReader.

    public static String getDiskFile_Lines( File file ) throws IOException {
        StringBuffer text = new StringBuffer();
        FileInputStream fileStream = new FileInputStream( file );
        BufferedReader br = new BufferedReader( new InputStreamReader( fileStream ) );
        for ( String line; (line = br.readLine()) != null; )
            text.append( line + System.lineSeparator() );
        return text.toString();
    }
    

Пример с основным методом для доступа к вышеуказанным методам.

public static void main(String[] args) throws IOException {
    String fileName = "E:/parametarisation.csv";
    File file = new File( fileName );

    String fileStream = commons_FileUtils( file );
            // guava_DiskFile( file );
            // streamFile_Buffer( file );
            // getDiskFile_Java7( file );
            // getDiskFile_Lines( file );
    System.out.println( " File Over Disk : \n"+ fileStream );


    try {
        String src = "https://code.jquery.com/jquery-3.2.1.js";
        URL url = new URL( src );

        String urlStream = commons_IOUtils( url );
                // guava_ServerFile( url );
                // streamURL_Scanner( url );
                // streamURL_Buffer( url );
        System.out.println( " File Over Network : \n"+ urlStream );
    } catch (MalformedURLException e) {
        e.printStackTrace();
    }
}

@видеть

Используя JDK 8 или выше:

внешние библиотеки не используются

Вы можете создать новый объект String из содержимого файла (используя классы из пакета java.nio.file):

public String readStringFromFile(String filePath) throws IOException {
    String fileContent = new String(Files.readAllBytes(Paths.get(filePath)));
    return fileContent;
}

Дубликат ответа Морица Петерсена, который написал: String content = new String (Files.readAllBytes (Paths.get (filename)), «UTF-8»);

Jean-Christophe Blanchard 29.11.2018 13:30

Начиная с JDK 11:

String file = ...
Path path = Paths.get(file);
String content = Files.readString(path);
// Or readString(path, someCharset), if you need a Charset different from UTF-8

Зачем, ну зачем вводить новые методы, основанные на кодировке по умолчанию в 2018 году?

mryan 24.09.2018 10:49

@mryan этот метод не полагается на системную кодировку по умолчанию. По умолчанию используется UTF-8, это нормально.

leventov 24.09.2018 14:39

@leventov ты прав! как и Files.readAllLines! что делает API файлов не очень совместимым со старыми методами, но это к лучшему :)

mryan 25.09.2018 16:34

Пользователь java.nio.Files читает все строки файла.

public String readFile() throws IOException {
        File fileToRead = new File("file path");
        List<String> fileLines = Files.readAllLines(fileToRead.toPath());
        return StringUtils.join(fileLines, StringUtils.EMPTY);
}

Другие вопросы по теме