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

1513

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

Есть ли лучший / другой способ прочитать файл в строку в 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();
    }
}
OscarRyz
источник
7
Может кто-нибудь объяснить мне очень просто, что с NIO? Каждый раз, когда я читаю об этом, я теряюсь в n-
ом
7
помните, что не гарантируется, что разделитель строк в файле не обязательно такой же, как системный разделитель строк.
Хенрик Пол
138
Не могли бы вы, наконец, вставить правильную попытку, которая закрывает читателя? Кто-то может использовать этот пример и внести ошибку в свой код.
Ганс-Петер Стёрр
6
Приведенный выше код содержит ошибку добавления дополнительного символа новой строки в последней строке. Это должно выглядеть примерно так: if (line = reader.readLine ())! = Null) {stringBuilder.append (line); } while (line = reader.readLine ())! = null) {stringBuilder.append (ls); stringBuilder.append (line); }
Deep
27
Java 7 знакомит с byte[] Files.readAllBytes(file);теми, кто предлагает «однострочное» решение для сканера: не нужно ли его закрывать?
Val

Ответы:

1536

Читать весь текст из файла

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при чтении файла встречается an, он оборачивается в 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 бит в файле) находятся в памяти одновременно. Безопаснее всего применять файлы, которые, как вы знаете, имеют небольшой размер относительно доступной памяти.

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

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

Эриксон
источник
3
Технически говоря, это O (n) во времени и пространстве. Качественно, из-за требования неизменности строк, это довольно тяжело для памяти; временно в памяти есть две копии данных char плюс пространство для закодированных байтов. Предполагая некоторую однобайтовую кодировку, для этого (временно) потребуется 5 байтов памяти для каждого символа в файле. Поскольку вопрос касается конкретно String, это то, что я показываю, но если вы можете работать с CharBuffer, возвращаемым функцией «decode», требования к памяти намного меньше. Что касается времени, я не думаю, что вы найдете что-то более быстрое в основных библиотеках Java.
Эриксон
5
Возможная опечатка? В NIO есть класс Charset (не CharSet), который называется java.nio.charset.Charset. Это то, чем должен был быть CharSet?
Джонатан Райт
31
Примечание: немного поработав над этим кодом, я обнаружил, что вы не можете надежно удалить файл сразу после прочтения с помощью этого метода, который в некоторых случаях может быть проблемой, но не моим. Может ли это быть связано с этой проблемой: bugs.sun.com/bugdatabase/view_bug.do?bug_id=4715154 ? Я наконец согласился с предложением Джона Скита, который не страдает от этой ошибки. В любом случае, я просто хотел дать информацию для других людей, на всякий случай ...
Себастьян Нуссбаумер
5
@ Себастьян Нуссбаумер: Я тоже столкнулся с этой проблемой. Удивительно, что ошибка была помечена как «не будет исправлена». По сути, это означает, что FileChannel#map, в общем, это непригодно для использования.
Joonas Pulakka
4
@ Sébastien Nussbaumer: ошибка была удалена из базы данных ошибок Oracle / Sun: «Эта ошибка недоступна». Google кэшировал сайт по адресу webcache.googleusercontent.com/search?q=cache:bugs.sun.com/…
bobndrew
351

Если вы хотите использовать внешнюю библиотеку, обратитесь к Apache Commons IO (JAR на 200 КБ). Он содержит 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
2
Это в классе org.apache.commons.io.FileUtils
Кирилл Ка
2
Я тоже использую FileUtils, но мне интересно, что лучше сделать, используя FileUtils или принятый ответ nio?
Гийом,
4
@Guillaume: Самый большой вопрос - комфортно ли вам иметь зависимость от сторонней библиотеки? Если в вашем проекте есть Commons IO или Guava , используйте его (просто для простоты кода; в противном случае заметного различия не будет).
Джоник
183

Очень бережливое решение, основанное на 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

Или с помощью блока try-with-resources , который будет вызывать 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.

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

Пабло Гризафи
источник
4
\\ A работает, потому что нет «другого начала файла», так что вы фактически прочитали последний токен ... который также является первым. Никогда не пробовал с \\ Z. Также обратите внимание, что вы можете читать все, что доступно для чтения, например Файлы, InputStreams, каналы ... Я иногда использую этот код для чтения из окна отображения затмения, когда я не уверен, что читаю тот или иной файл ... .yes, classpath смущает меня.
Пабло Гризафи
1
Как автор, я могу сказать, что действительно не знаю, правильно ли и когда файл закрыт ... Я никогда не пишу этот файл в рабочем коде, я использую его только для тестирования или отладки.
Пабло Гризафи
2
Он имеет предел в 1024 символа, я думаю
Причудливый
20
Сканер реализует Closeable (он вызывает close на источнике) - так что, хотя он и элегантен, он не должен быть однострочным. Размер буфера по умолчанию - 1024, но Scanner при необходимости увеличит его размер (см. Scanner # makeSpace ())
earcam
8
Этот сбой для пустых файлов с java.util.NoSuchElementException.
SpaceTrucker
117
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 вы можете сделать это таким образом.

JoBⅈN
источник
Это должно быть принято как ответ - одна строка, никаких внешних библиотек.
Черри
Это добавило символ новой строки в конце, даже если его не было в файле
Стефан Хаберл
79

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

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();
    }
}
Донал
источник
2
Я думаю, что это лучший способ. Проверьте java.sun.com/docs/books/tutorial/essential/io/scanning.html
Tarski
3
Конструктор Scanner, который принимает строку, обрабатывает строку не как имя файла для чтения, а как текст для сканирования. Я делаю эту ошибку все время. : - /
Алан Мур
@ Алан, хороший улов. Я слегка отредактировал ответ Дона, чтобы исправить это (надеюсь).
Джоник
3
fileContents.append (scanner.nextLine ()) Append (lineSeparator).
запрет геоинженерии
1
Измените оператор инициализации на Scanner scanner = new Scanner((Readable) new BufferedReader(new FileReader(file)));. В противном случае вы можете захватить только часть файла.
Вэй Ян
71

У Guava есть метод, похожий на метод из Commons IOUtils, о котором упоминал Вилли аус Рор:

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

// ...

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

EDIT от PiggyPiglet
Files#toString устарел и подлежит удалению Octobor 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. Текущий источник см. В классах Files , CharStreams , ByteSource и CharSource в пакете com.google.common.io .

OscarRyz
источник
Этот код имеет приведение типа long к int, что может привести к сумасшедшему поведению с большими файлами. Есть ли дополнительные пробелы и где вы закрываете входной поток?
Мохамед Тахер Alrefaie
@MTA: поток будет закрыт, обратите внимание на использование Closerв CharSource . Код в ответе не является действительным, текущим источником Guava.
Джоник
54
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 "";
    }
user590444
источник
6
Или еще проще:new String(Files.readAllBytes(FileSystems.getDefault().getPath( filename)));
12
или new String(Files.readAllBytes(Paths.get(filename)));:-)
assafmo
1
Хорошо сыграно, и, чтобы спасти следующего парня, PathsГуглинг , по-видимому, 1,7+ как есть FileSystems. (Черт
возьми
4
Жаль, что у этого ответа нет больше голосов. Я искал самый быстрый и простой способ получить текстовый файл в строку. Вот и все, и если бы я не прокручивал вниз и вниз и вниз, я бы пропустил это. ФП должен рассмотреть возможность принятия этого ответа, чтобы переместить его на вершину.
Торн
@Thorn У этого ответа ужасная обработка ошибок. Не используйте этот метод в рабочем коде, или лучше: никогда.
xehpuk
51

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

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 () после того, как вы прочитали строки или до этого?
Иштван
Реальная работа начинается с момента вызова операции терминала (...). Поток лениво заселяется построчно. Нет необходимости читать весь файл в памяти перед обработкой (например, фильтрация и отображение).
Андрей N
обрезать перед выбором непустые строки?
Турбьёрн Равн Андерсен
50

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

Вот альтернатива, которая этого не делает и которая (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();
    }        
}
Джон Скит
источник
1
Простите, что оживил этот старый комментарий, но вы хотели передать объект String с именем «file», или это должен быть объект File?
Брайан Ларсон
28

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

  • Гуава: 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();
    }
}

@видеть

Яши
источник
26

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

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

public static String readFileToString(File file) throws IOException

Если вы хотите, чтобы строки были списком, используйте

public static List<String> readLines(File file) throws IOException
Дом во времени
источник
25

С 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
leventov
источник
Зачем, ну почему, вводить новые методы, основанные на кодировке по умолчанию в 2018 году?
Мрян,
2
@mryan этот метод не использует системную кодировку по умолчанию. По умолчанию это UTF-8, это нормально.
Левентов
@leventov ты прав! как и Files.readAllLines! это делает
файловый
17

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

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();
    }
}
Питер Лори
источник
16

В Java 7 это мой предпочтительный вариант для чтения файла UTF-8:

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

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

Мориц Петерсен
источник
15

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

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

Ваша лучшая ставка, вероятно, вторая, поскольку она имеет наименьшее количество зависимостей.

Клаудиу
источник
4
Yeap. Это заставляет язык «высокого уровня» принимать другое значение. Java - высокий уровень по сравнению с C, но низкий по сравнению с Python или Ruby
OscarRyz
3
Согласитесь, что в Java много абстракций высокого уровня, но мало удобных методов
Dónal
3
Правда, у Java есть безумное количество способов работы с файлами, и многие из них кажутся сложными. Но это довольно близко к тому, что мы имеем в языках более высокого уровня:byte[] bytes = Files.readAllBytes(someFile.toPath());
Торн
11

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

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

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

public String readStringFromFile(String filePath) throws IOException {
    String fileContent = new String(Files.readAllBytes(Paths.get(filePath)));
    return fileContent;
}
Saikat
источник
Дубликат ответа Морица Петерсена, который написал: String content = new String (Files.readAllBytes (Paths.get (filename)), "UTF-8");
Жан-Кристоф Бланшар
8

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

for(String line = reader.readLine(); line != null; line = reader.readLine()) {
    stringBuilder.append(line);
    stringBuilder.append(ls);
}
Дэн Дайер
источник
3
Это изменит символы новой строки на выбор новой строки по умолчанию. Это может быть желательным или непреднамеренным.
Питер Лори
Откатил редактирование этого ответа, потому что целью было сузить область действия lineпеременной. Редактирование объявляло это дважды, что было бы ошибкой компиляции.
Дэн Дайер
7

Если у вас нет доступа к 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
4

Гибкое решение, использующее 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.

Вау
источник
3

Имейте в 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.

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

Этот использует метод 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
        }
    }
}
barjak
источник
3

Вы можете попробовать сканер и файл класса, несколько строк решения

 try
{
  String content = new Scanner(new File("file.txt")).useDelimiter("\\Z").next();
  System.out.println(content);
}
catch(FileNotFoundException e)
{
  System.out.println("not found!");
}
jamesjara
источник
3

Пользователь, 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);
}
Нитин Вавдия
источник
3
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
7
Мне кажется, что блок finally не знает переменных, определенных в блоке try. javac 1.6.0_21 выдает ошибку cannot find symbol.
ceving
Вы даже пробовали свой собственный код? Вы определили читателя в блоке try / catch, поэтому он не будет доступен в блоке finally.
mauron85
2

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

Один из лучших ответов здесь ( 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();
    }
}
Ajk
источник
В первом случае вы можете добавить дополнительную новую строку в конце. во втором случае вы можете пропустить один. Так что оба одинаково неправы. Смотрите эту статью
Патрик Паркер
2

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

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 должны быть вещи, которые должны работать лучше.

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

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

Хаакон Лотвейт
источник
2

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

String data = IO.from(new File("data.txt")).toString();
Сатнам
источник
1
если строки внутри библиотеки не учитываются
Ари
2

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

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");
OscarRyz
источник
2

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

String sMessage = String.join("\n", reader.lines().collect(Collectors.toList()));
Малкольм Бекхофф
источник
2

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

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()]));
}
Muskovets
источник