При работе над корпоративным приложением иногда возникает необходимость записывать текстовые или двоичные данные в файлы на Java, например, записывать созданные пользователем отчеты в файловую систему.
Хотя существует множество способов записи файлов в Java, давайте быстро рассмотрим некоторые из них, чтобы иметь возможность быстро воспользоваться ими при необходимости.
Содержимое строки = "какой-то текст";// Ява 11Files.writeString(Path.of("demo.txt"), content);// Использование класса FilesФайлы.write(Path.of("demo.txt"), content.getBytes());// Использование BufferedWriterпопробуйте(BufferedWriter writer = new BufferedWriter(new FileWriter(filePath.toFile()))) {писатель.запись(контент);}// Использование FileWritertry(FileWriter fileWriter = new FileWriter(Path.of("demo.txt").toFile())){fileWriter.write(контент);}// Запись в двоичный файлtry(FileOutputStream outputStream = new FileOutputStream(Path.of("demo.txt").toFile())){byte[] strToBytes = content.getBytes();outputStream.write(strToBytes);}
1. Использование Files.writeString() – Java 11
Начиная с Java 11, метод Files.writeString() предлагает удобный способ записи текста в файл. Он принимает параметр Path и строку, упрощая процесс записи текстового содержимого в однострочном операторе.
- Как следует из названия, метод writeString() используется для записи символьных/текстовых данных в файлы.
- Все символы пишутся как есть, включая разделители строк. Дополнительные символы не добавляются.
- По умолчанию используется кодировка символов UTF-8.
- Он выдает исключение IOException, если при записи или создании файла возникает ошибка ввода-вывода или если текст не может быть закодирован с использованием указанного набора символов.
Path filePath = Path.of("demo.txt");String content = "hello world !!";Files.writeString(filePath, content);
2. Запись в файл с помощью Files.write()
Класс Files — это еще один метод write(), начиная с Java 7, и он работает аналогично writeString(). Он принимает Path и массив байтов в качестве параметров.
Метод write() подходит для записи двоичных данных, а также его можно использовать для записи текстовых данных, как показано в следующем примере.
Path filePath = Path.of("demo.txt");String content = "hello world !!";//Write bytesFiles.write(filePath, content.getBytes());//Write linesList<String> lines = Arrays.asList("a", "b", "c");Files.write(filePath, lines, StandardCharsets.UTF_8);
3. Быстрая запись с помощью FileChannel и ByteBuffer
FileChannel может использоваться для чтения, записи, отображения и манипулирования файлом. Если мы записываем большие файлы, FileChannel может быть быстрее стандартного IO.
Файловые каналы безопасны для использования несколькими параллельными потоками.
Path fileName = Path.of("demo.txt");String content = "hello world !!";try(RandomAccessFile stream = new RandomAccessFile(filePath.toFile(),"rw");FileChannel channel = stream.getChannel();) {byte[] strBytes = content.getBytes();ByteBuffer buffer = ByteBuffer.allocate(strBytes.length);buffer.put(strBytes);buffer.flip();channel.write(buffer);}
4. Запись в текстовый файл с помощью BufferedWriter
BufferedWriter — наиболее традиционный и простой способ записи содержимого в файл. Он записывает текст в поток вывода символов, буферизуя символы, чтобы обеспечить эффективную запись отдельных символов, массивов и строк.
Если не требуется быстрый вывод, рекомендуется обернуть BufferedWriter вокруг любого Writer, операции write() которого могут быть затратными, например FileWriter и OutputStreamWriter, особенно при записи больших объемов данных.
Поскольку перед записью выполняется буферизация, это приводит к уменьшению количества операций ввода-вывода, что повышает производительность.
Path filePath = Path.of("demo.txt");String content = "hello world !!";try(BufferedWriter writer = new BufferedWriter(new FileWriter(filePath.toFile()))) {writer.write(content);}
5. Запись в файл с помощью FileWriter или PrintWriter
FileWriter — самый чистый способ записи файлов, синтаксис не требует пояснений, его легко читать и понимать. FileWriter записывает данные непосредственно в файл(производительность ниже), и его следует использовать только при небольшом количестве записей.
Поскольку FileWriter не обеспечивает буферизацию, это может привести к проблемам с производительностью при записи больших объемов данных.
Path filePath = Path.of("demo.txt");String content = "hello world !!";try(FileWriter fileWriter = new FileWriter(filePath.toFile())){fileWriter.write(content);}
Используйте PrintWriter для записи форматированного текста в файл. Этот класс реализует все методы печати, найденные в PrintStream, поэтому вы можете использовать все форматы, которые вы используете с операторами System.out.println().
Path filePath = Path.of("demo.txt");String content = "hello world !!";try(FileWriter fileWriter = new FileWriter(filePath.toFile());PrintWriter printWriter = new PrintWriter(fileWriter);){printWriter.print(content);printWriter.printf("Blog name is %s", "howtodoinjava.com");}
6. Запись в двоичный файл с помощью FileOutputStream
Используйте FileOutputStream для записи двоичных данных в файл. FileOutputStream предназначен для записи потоков необработанных байтов, таких как данные изображений. Для записи потоков символов рассмотрите возможность использования FileWriter.
Path filePath = Path.of("demo.txt");String content = "hello world !!";try(FileOutputStream outputStream = new FileOutputStream(filePath.toFile())){byte[] strToBytes = content.getBytes();outputStream.write(strToBytes);}
7. Запись в файл с помощью DataOutputStream
DataOutputStream позволяет приложению записывать примитивные типы данных Java в выходной поток переносимым способом. Затем приложение может использовать входной поток данных для обратного чтения данных.
Path filePath = Path.of("demo.txt");String content = "hello world !!";try(FileOutputStream outputStream= new FileOutputStream(filePath.toFile());DataOutputStream dataOutStream= new DataOutputStream(new BufferedOutputStream(outputStream));) {dataOutStream.writeUTF(content);dataOutStream.writeInt(10);dataOutStream.writeLong(100L);}
7. Чистый код против производительности
При оценке производительности следует учитывать ряд факторов:
- Удобство: Files.writeString() наиболее удобен для записи текстовых данных, в то время как Files.write() подходит для двоичных данных. Эти методы предоставляют простой в использовании API.
- Буферизация: BufferedWriter и Files.write() обеспечивают буферизацию, которая может значительно повысить производительность записи, особенно при работе с большими объемами данных.
- Двоичные данные против текстовых: Если вам нужно записывать двоичные данные, FileOutputStream — лучший выбор. Для текстовых данных решение зависит от уровня удобства и необходимости буферизации, как обсуждалось выше.
Для меньших файлов мы можем предпочесть читабельность, перевешивающую другие факторы, поскольку выигрыш в производительности будет незначительным. FileWriter и Files.writeString() должны быть предпочтительными вариантами в случае меньших файлов.
Для большого объема данных нам потребуется лучшая сырая производительность. В этом случае буферизованные методы, такие как BufferedWriter и Files.write(), могут предложить улучшенную эффективность.
В конечном итоге выбор метода должен зависеть от конкретных требований, таких как объем данных, простота и читаемость.
8. Резюме
- Если мы попытаемся выполнить запись в несуществующий файл, файл будет сначала создан, и исключение не возникнет(за исключением использования метода Path).
- Всегда закрывайте выходной поток после записи содержимого файла, чтобы освободить все ресурсы. Это также поможет не повредить файл.
- PrintWriter используется для записи форматированного текста.
- Используйте FileOutputStream для записи двоичных данных.
- Используйте DataOutputStream для записи примитивных типов данных.
- Используйте FileChannel для записи больших файлов. Это также предпочтительный способ записи файлов в Java 8.