Как создать строку 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(); } } 

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

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

 List lines = Files.readAllLines(Paths.get(path), encoding); 

В Java 8 BufferedReader добавила новый метод, lines() чтобы создать Stream . Если при чтении файла встречается исключение IOException , оно завершается в исключении UncheckedIOException , поскольку Stream не принимает lambdas, которые выбрали проверенные исключения.

 try (BufferedReader r = Files.newBufferedReader(path, encoding)) { r.lines().forEach(System.out::println); } 

Существует также метод Files.lines() который делает что-то очень похожее, возвращая Stream напрямую. Но мне это не нравится. Stream требует вызова close() ; это плохо документировано в API, и я подозреваю, что многие люди даже не замечают, что Stream имеет метод close() . Таким образом, ваш код будет выглядеть очень похоже, например:

 try (Stream lines = Files.lines(path, encoding)) { lines.forEach(System.out::println); } 

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

Использование памяти

Первый метод, который сохраняет разрывы строк, может временно потребовать памяти в несколько раз больше размера файла, потому что на короткое время содержимое необработанного файла (байтовый массив) и декодированные символы (каждый из которых составляет 16 бит, даже если кодируется как 8 бит в файле) одновременно находятся в памяти. Безопаснее всего применять к файлам, которые, как известно, малы относительно доступной памяти.

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

Для чтения больших файлов вам нужен другой дизайн для вашей программы, который читает fragment текста из streamа, обрабатывает его и затем переходит к следующему, повторно используя один и тот же блок памяти фиксированного размера. Здесь «большой» зависит от характеристик компьютера. В настоящее время этот порог может быть много гигабайт оперативной памяти. Третий метод, используя Stream является одним из способов сделать это, если ваши «записи» ввода являются отдельными линиями. (Использование метода readLine() BufferedReader является процедурным эквивалентом этого подхода.)

Кодировка символов

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

Класс StandardCharsets определяет некоторые константы для кодировок, требуемых для всех Java-приложений:

 String content = readFile("test.txt", StandardCharsets.UTF_8); 

По умолчанию платформа доступна из classа Charset :

 String content = readFile("test.txt", Charset.defaultCharset()); 

Примечание. Этот ответ в значительной степени заменяет мою версию Java 6. Утилита Java 7 безопасно упрощает код, а старый ответ, который использовал отображенный байт-буфер, предотвратил удаление файла, который был прочитан, до тех пор, пока отображаемый буфер не будет собран мусором. Вы можете просмотреть старую версию с помощью «отредактированной» ссылки на этот ответ.

Commons FileUtils.readFileToString :

 public static String readFileToString(File file) throws IOException 

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

Параметры:

  • file – файл для чтения, не должен быть нулевым

Возвращает: содержимое файла, никогда не имеет значения

Броски: – IOException – в случае ошибки ввода-вывода

Начиная с: Commons IO 1.3.1

Код, используемый (косвенно) этим classом:

IOUtils.java под лицензией Apache 2.0 .

 public static long copyLarge(InputStream input, OutputStream output) throws IOException { byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; long count = 0; int n = 0; while (-1 != (n = input.read(buffer))) { output.write(buffer, 0, n); count += n; } return count; } 

Он очень похож на тот, который используется Ritche_W.

На этой странице очень сухое решение:

 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 

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

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

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

У Гувы есть метод, подобный методу из Commons IOUtils, который Вилли Аус Рор упомянул:

 import com.google.common.base.Charsets; import com.google.common.io.Files; // ... String text = Files.toString(new File(path), Charsets.UTF_8); 

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

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

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

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

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

Если вам нужна обработка строк (parallel processing), 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"))); 

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

Вот альтернатива, которая этого не делает, и которая (ИМО) проще понять, чем код 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 content = new String(Files.readAllBytes(Paths.get("readMe.txt")), "UTF-8"); 

так как java 7 можно сделать так.

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

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

 public static String readFileToString(File file) throws IOException 

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

 public static List readLines(File file) throws IOException 

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

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

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

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

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

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

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

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

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

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

Поскольку 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 
 public static String slurp (final File file) throws IOException { StringBuilder result = new StringBuilder(); try { BufferedReader reader = new BufferedReader(new FileReader(file)); 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(); } 

Если у вас нет доступа к файлам, вы делаете следующее:

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

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

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

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

 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.

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

Вы можете попробовать сканер и class 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!"); } 

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

  • Гуава: Google использует classы 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 – COMMONS IO, используя classы 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 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 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(); } } 

@видеть

  • Способы преобразования InputStream в строку

После Ctrl + F’ing после сканера, я думаю, что решение 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-in-resources, чтобы сделать код более удобным для чтения. Больше ничего не забивает все. Но это в основном стилистический выбор.

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

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

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

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

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

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

 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 lines = Files.readAllLines(new File(fileName).toPath()); return String.join("\n", lines.toArray(new String[lines.size()])); } 

Использование JDK 8 или выше:

не использовались внешние библиотеки

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

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

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

Один из лучших ответов здесь ( 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(); } } 

Использовать код:

 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 contains output in String.

  • Как преобразовать InputStream в виртуальный файл
  • Что такое идиома C ++, эквивалентная статическому блоку Java?
  • Получить компонент Swing по имени
  • Как сделать редактор таблиц JComboBox иметь дизайн обычного JComboBox?
  • В критических разделах Java, на что я должен синхронизироваться?
  • Потоковая передача больших файлов в сервлет Java
  • Как отформатировать строку Java с начальным нулем?
  • Какой был бы самый быстрый метод тестирования на простоту Java?
  • При использовании == для примитива и значения в коробке выполняется автобоксирование или выполняется распаковка
  • Как я могу увеличить дату на один день в Java?
  • Есть ли один JVM для Java-приложения?
  • Interesting Posts

    Есть ли ярлык для SELECT * FROM?

    Привязать событие к щелчку правой кнопкой мыши

    Совокупность / суммирование нескольких переменных для каждой группы (например, сумма, среднее значение)

    Я хочу выполнять команды в цикле одновременно, а не один за другим

    Стабилизация стандартной библиотеки qsort?

    Могу ли я навсегда запретить обновлениям безопасности Java от установки панели инструментов Yahoo?

    Медленная передача файлов по сети между двумя ноутбуками 802.11n (подключается непосредственно через точку доступа)

    Панель действий Android SearchView как автозаполнение?

    R: ggplot не работает, если он находится внутри цикла for, хотя он работает вне него

    PowerPoint: отображать только объекты, относящиеся к определенному шагу анимации

    Вложение небольших участков внутри подзаголовков в matplotlib

    Android BroadcastReceiver в действии

    Контролируемые и неконтролируемые компоненты ReactJs

    Ярлык для перезагрузки фрейма в Firefox?

    Изменение размера UIImage (пропорция шкалы)

    Давайте будем гением компьютера.