Чтение и запись файлов на Java

Введение В этой статье мы углубимся в чтение и запись файлов на Java. При программировании, независимо от того, создаете ли вы мобильное приложение, веб-приложение или просто пишете сценарии, вам часто нужно читать или записывать данные в файл. Эти данные могут быть данными кеша, данными, полученными вами для набора данных, изображением или чем-либо еще, что вы можете придумать. В этом руководстве мы покажем наиболее распространенные способы чтения и записи файлов в Java. Java предоставляет несколько API (также

Вступление

В этой статье мы углубимся в чтение и запись файлов на Java .

При программировании, независимо от того, создаете ли вы мобильное приложение, веб-приложение или просто пишете сценарии, вам часто нужно читать или записывать данные в файл. Эти данные могут быть данными кеша, данными, полученными вами для набора данных, изображением или чем-либо еще, что вы можете придумать.

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

Java предоставляет несколько API (также известных как Java I / O ) для чтения и записи файлов с момента его первых выпусков. В последующих выпусках ввод-вывод Java был улучшен, упрощен и расширен для поддержки новых функций.

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

Потоки ввода / вывода

Есть два типа потоков, которые вы можете использовать для взаимодействия с файлами:

  1. Потоки персонажей
  2. Байтовые потоки

Для каждого из вышеперечисленных типов потоков есть несколько поддерживающих классов, поставляемых с Java, которые мы кратко рассмотрим ниже.

Потоки персонажей

Потоки символов используются для чтения или записи типа данных символов. Давайте посмотрим на наиболее часто используемые классы. Все эти классы определены в пакете java.io

Вот несколько классов, которые вы должны знать, которые можно использовать для чтения символьных данных:

  • Читатель
    абстрактный класс для чтения потока символов.
  • InputStreamReader
    класс, используемый для чтения байтового потока и преобразования в символьный поток.
  • FileReader
    класс для чтения символов из файла.
  • BufferedReader
    это оболочка над Reader , поддерживающая возможности буферизации. Во многих случаях это наиболее предпочтительный класс для чтения данных, поскольку за один read() из файла может быть прочитано больше данных, что сокращает количество фактических операций ввода-вывода с файловой системой.

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

  • Writer
    это абстрактный класс для записи символьных потоков.
  • OutputStreamWriter
    этот класс используется для записи символьных потоков, а также их преобразования в байтовые потоки.
  • FileWriter
    класс для записи символов в файл.
  • BufferedWriter
    это оболочка над Writer , который также поддерживает возможности буферизации. Это наиболее предпочтительный класс для записи данных в файл, поскольку за один вызов write() Как и BufferedReader , это уменьшает общее количество операций ввода-вывода с файловой системой.

Байтовые потоки

Потоки байтов используются для чтения или записи байтовых данных с файлами. Это отличается от предыдущего способом обработки данных. Здесь вы работаете с необработанными байтами, которые могут быть символами, данными изображения, данными Unicode (для представления символа требуется 2 байта) и т. Д.

В этом разделе мы рассмотрим наиболее часто используемые классы. Все эти классы определены в пакете java.io

Вот классы, используемые для чтения байтовых данных:

  • InputStream
    абстрактный класс для чтения байтовых потоков.
  • FileInputStream
    класс для простого чтения байтов из файла.
  • BufferedInputStream
    это оболочка над InputStream которая поддерживает возможности буферизации. Как мы видели в потоках символов, это более эффективный метод, чем FileInputStream .

А вот классы, используемые для записи байтовых данных:

  • OutputStream
    абстрактный класс для записи байтовых потоков.
  • FileOutputStream
    класс для записи необработанных байтов в файл.
  • ByteOutputStream
    этот класс является оболочкой над OutputStream для поддержки возможностей буферизации. И снова, как мы видели в потоках символов, это более эффективный метод, чем FileOutputStream благодаря буферизации.

Потоки Java NIO

Java NIO

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

Буферы, селекторы и каналы - три основных компонента Java NIO, хотя в этой статье мы сосредоточимся строго на использовании классов NIO для взаимодействия с файлами, а не обязательно на концепциях, лежащих в основе API.

Поскольку это руководство посвящено чтению и записи файлов, в этом коротком разделе мы обсудим только связанные классы:

  • Путь
    это иерархическая структура фактического расположения файла, которая обычно используется для поиска файла, с которым вы хотите взаимодействовать.
  • Пути
    это класс, который предоставляет несколько служебных методов для создания Path из заданного строкового URI.
  • Файлы
    это еще один служебный класс, который имеет несколько методов для чтения и записи файлов без блокировки выполнения в потоках.

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

Разница между вводом-выводом Java и NIO

Основное различие между этими двумя пакетами заключается в том, что read() и write() Java IO являются блокирующими вызовами. Под этим мы подразумеваем, что поток, вызывающий один из этих методов, будет заблокирован до тех пор, пока данные не будут прочитаны или записаны в файл.

С другой стороны, в случае NIO методы неблокирующие. Это означает, что вызывающие потоки могут выполнять другие задачи (например, чтение / запись данных из другого источника или обновление пользовательского интерфейса), в то время write read или записи ожидают завершения своей операции. Это может привести к значительному увеличению производительности, если вы имеете дело с большим количеством запросов ввода-вывода или большого количества данных.

Примеры чтения и записи текстовых файлов

В предыдущих разделах мы обсудили различные API, предоставляемые Java, и теперь пора использовать эти классы API в некотором коде.

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

Примечание . Чтобы избежать путаницы в пути к файлу, пример кода будет читать и писать из файла в домашнем каталоге пользователя. Домашний каталог пользователя можно найти с помощью System.getProperty("user.home"); , что мы и используем в наших примерах.

Чтение и запись с помощью FileReader и FileWriter

Начнем с использования классов FileReader и FileWriter

 String directory = System.getProperty("user.home"); 
 String fileName = "sample.txt"; 
 String absolutePath = directory + File.separator + fileName; 
 
 // Write the content in file 
 try(FileWriter fileWriter = new FileWriter(absolutePath)) { 
 String fileContent = "This is a sample text."; 
 fileWriter.write(fileContent); 
 fileWriter.close(); 
 } catch (IOException e) { 
 // Cxception handling 
 } 
 
 // Read the content from file 
 try(FileReader fileReader = new FileReader(absolutePath)) { 
 int ch = fileReader.read(); 
 while(ch != -1) { 
 System.out.print((char)ch); 
 fileReader.close(); 
 } 
 } catch (FileNotFoundException e) { 
 // Exception handling 
 } catch (IOException e) { 
 // Exception handling 
 } 

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

Метод write() записывает допустимую последовательность символов - либо String , либо char[] . Кроме того, он может записать один char представленный как int .

read() метод считывает и возвращает символ за символом, что позволяет нам использовать считанные данные в while петли, например.

Не забудьте закрыть оба этих класса после использования!

Чтение и запись с помощью BufferedReader и BufferedWriter

Использование классов BufferedReader и BufferedWriter

 String directory = System.getProperty("user.home"); 
 String fileName = "sample.txt"; 
 String absolutePath = directory + File.separator + fileName; 
 
 // Write the content in file 
 try(BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(absolutePath))) { 
 String fileContent = "This is a sample text."; 
 bufferedWriter.write(fileContent); 
 } catch (IOException e) { 
 // Exception handling 
 } 
 
 // Read the content from file 
 try(BufferedReader bufferedReader = new BufferedReader(new FileReader(absolutePath))) { 
 String line = bufferedReader.readLine(); 
 while(line != null) { 
 System.out.println(line); 
 line = bufferedReader.readLine(); 
 } 
 } catch (FileNotFoundException e) { 
 // Exception handling 
 } catch (IOException e) { 
 // Exception handling 
 } 

Чтение и запись с помощью FileInputStream и FileOutputStream

Использование FileInputStream и FileOutputStream :

 String directory = System.getProperty("user.home"); 
 String fileName = "sample.txt"; 
 String absolutePath = directory + File.separator + fileName; 
 
 // write the content in file 
 try(FileOutputStream fileOutputStream = new FileOutputStream(absolutePath)) { 
 String fileContent = "This is a sample text."; 
 fileOutputStream.write(fileContent.getBytes()); 
 } catch (FileNotFoundException e) { 
 // exception handling 
 } catch (IOException e) { 
 // exception handling 
 } 
 
 // reading the content of file 
 try(FileInputStream fileInputStream = new FileInputStream(absolutePath)) { 
 int ch = fileInputStream.read(); 
 while(ch != -1) { 
 System.out.print((char)ch); 
 ch = fileInputStream.read(); 
 } 
 } catch (FileNotFoundException e) { 
 // exception handling 
 } catch (IOException e) { 
 // exception handling 
 } 

Чтение и запись с помощью BufferedInputStream и BufferedOutputStream

Использование классов BufferedInputStream и BufferedOutputStream

 String directory = System.getProperty("user.home"); 
 String fileName = "sample.txt"; 
 String absolutePath = directory + File.separator + fileName; 
 
 // write the content in file 
 try(BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(absolutePath))) { 
 String fileContent = "This is a sample text."; 
 bufferedOutputStream.write(fileContent.getBytes()); 
 } catch (IOException e) { 
 // exception handling 
 } 
 
 // read the content from file 
 try(BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(absolutePath))) { 
 int ch = bufferedInputStream.read(); 
 while(ch != -1) { 
 System.out.print((char)ch); 
 ch = bufferedInputStream.read(); 
 } 
 } catch (FileNotFoundException e) { 
 // exception handling 
 } catch (IOException e) { 
 // exception handling 
 } 

Чтение и запись с помощью классов Java.nio

Используя классы java.nio

 String directory = System.getProperty("user.home"); 
 String fileName = "sample.txt"; 
 
 String content = "This is a sample text."; 
 Path path = Paths.get(directory, fileName); 
 
 try { 
 Files.write(path, content.getBytes(), StandardOpenOption.CREATE); 
 } catch (IOException e) { 
 // exception handling 
 } 
 
 try { 
 List<String> list = Files.readAllLines(path); 
 list.forEach(line -> System.out.println(line)); 
 } catch (IOException e) { 
 // exception handling 
 } 

Другой способ получить содержимое через Files , что более важно, если вы не читаете текстовые данные, - это использовать readAllBytes для чтения данных в массив байтов:

 try { 
 byte[] data = Files.readAllBytes(path); 
 System.out.println(new String(data)); 
 } catch (IOException e) { 
 // exception handling 
 } 

Если вы заинтересованы в использовании потоков с java.nio , вы также можете использовать следующие методы, предоставляемые Files , которые работают так же, как потоки, которые мы рассмотрели ранее в статье:

 Files.newBufferedReader(path) 
 Files.newBufferedWriter(path, options) 
 Files.newInputStream(path, options) 
 Files.newOutputStream(path, options) 

Заключение

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

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus