Рубрики
Без рубрики

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

В этом уроке мы будем читать и записывать файлы на Java с помощью FileReader, FileWriter, BufferedReader, BufferedWriter, FileInputStream, FileOutputStream и т. Д.

Автор оригинала: Scott Robinson.

Вступление

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

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

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

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

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

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

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

  1. Потоки символов
  2. Потоки байтов

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

Потоки символов

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

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

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

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

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

Потоки байтов

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

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

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

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

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

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

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

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

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

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

Git Essentials

Ознакомьтесь с этим практическим руководством по изучению Git, содержащим лучшие практики и принятые в отрасли стандарты. Прекратите гуглить команды Git и на самом деле изучите это!

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

Чтение и запись с помощью программы чтения файлов и пишущей машинки

Давайте начнем с использования классов FileReader и Пишущая машинка :

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
}

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

Метод write() записывает допустимую последовательность символов – либо Строку , либо символ[] . Кроме того, он может записать один символ , представленный как 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 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, и, кроме того, код немного более удобен для обслуживания и чтения.