Как правильно записывать байты в файл java

от admin

Reading, Writing, and Creating Files

This page discusses the details of reading, writing, creating, and opening files. There are a wide array of file I/O methods to choose from. To help make sense of the API, the following diagram arranges the file I/O methods by complexity.

File I/O Methods Arranged from Less Complex to More Complex

On the far left of the diagram are the utility methods readAllBytes , readAllLines , and the write methods, designed for simple, common cases. To the right of those are the methods used to iterate over a stream or lines of text, such as newBufferedReader , newBufferedWriter , then newInputStream and newOutputStream . These methods are interoperable with the java.io package. To the right of those are the methods for dealing with ByteChannels , SeekableByteChannels , and ByteBuffers , such as the newByteChannel method. Finally, on the far right are the methods that use FileChannel for advanced applications needing file locking or memory-mapped I/O.

This page has the following topics:

The OpenOptions Parameter

Several of the methods in this section take an optional OpenOptions parameter. This parameter is optional and the API tells you what the default behavior is for the method when none is specified.

The following StandardOpenOptions enums are supported:

  • WRITE – Opens the file for write access.
  • APPEND – Appends the new data to the end of the file. This option is used with the WRITE or CREATE options.
  • TRUNCATE_EXISTING – Truncates the file to zero bytes. This option is used with the WRITE option.
  • CREATE_NEW – Creates a new file and throws an exception if the file already exists.
  • CREATE – Opens the file if it exists or creates a new file if it does not.
  • DELETE_ON_CLOSE – Deletes the file when the stream is closed. This option is useful for temporary files.
  • SPARSE – Hints that a newly created file will be sparse. This advanced option is honored on some file systems, such as NTFS, where large files with data "gaps" can be stored in a more efficient manner where those empty gaps do not consume disk space.
  • SYNC – Keeps the file (both content and metadata) synchronized with the underlying storage device.
  • DSYNC – Keeps the file content synchronized with the underlying storage device.

Commonly Used Methods for Small Files

Reading All Bytes or Lines from a File

If you have a small-ish file and you would like to read its entire contents in one pass, you can use the readAllBytes(Path) or readAllLines(Path, Charset) method. These methods take care of most of the work for you, such as opening and closing the stream, but are not intended for handling large files. The following code shows how to use the readAllBytes method:

Writing All Bytes or Lines to a File

You can use one of the write methods to write bytes, or lines, to a file.

  • write(Path, byte[], OpenOption. )
  • write(Path, Iterable< extends CharSequence>, Charset, OpenOption. )

The following code snippet shows how to use a write method.

Buffered I/O Methods for Text Files

The java.nio.file package supports channel I/O, which moves data in buffers, bypassing some of the layers that can bottleneck stream I/O.

Reading a File by Using Buffered Stream I/O

The newBufferedReader(Path, Charset) method opens a file for reading, returning a BufferedReader that can be used to read text from a file in an efficient manner.

The following code snippet shows how to use the newBufferedReader method to read from a file. The file is encoded in "US-ASCII."

Writing a File by Using Buffered Stream I/O

You can use the newBufferedWriter(Path, Charset, OpenOption. ) method to write to a file using a BufferedWriter .

The following code snippet shows how to create a file encoded in "US-ASCII" using this method:

Methods for Unbuffered Streams and Interoperable with java.io APIs

Reading a File by Using Stream I/O

To open a file for reading, you can use the newInputStream(Path, OpenOption. ) method. This method returns an unbuffered input stream for reading bytes from the file.

Creating and Writing a File by Using Stream I/O

You can create a file, append to a file, or write to a file by using the newOutputStream(Path, OpenOption. ) method. This method opens or creates a file for writing bytes and returns an unbuffered output stream.

The method takes an optional OpenOption parameter. If no open options are specified, and the file does not exist, a new file is created. If the file exists, it is truncated. This option is equivalent to invoking the method with the CREATE and TRUNCATE_EXISTING options.

The following example opens a log file. If the file does not exist, it is created. If the file exists, it is opened for appending.

Methods for Channels and ByteBuffers

Reading and Writing Files by Using Channel I/O

While stream I/O reads a character at a time, channel I/O reads a buffer at a time. The ByteChannel interface provides basic read and write functionality. A SeekableByteChannel is a ByteChannel that has the capability to maintain a position in the channel and to change that position. A SeekableByteChannel also supports truncating the file associated with the channel and querying the file for its size.

The capability to move to different points in the file and then read from or write to that location makes random access of a file possible. See Random Access Files for more information.

There are two methods for reading and writing channel I/O.

  • newByteChannel(Path, OpenOption. )
  • newByteChannel(Path, Set<? extends OpenOption>, FileAttribute<?>. )

Both newByteChannel methods enable you to specify a list of OpenOption options. The same open options used by the newOutputStream methods are supported, in addition to one more option: READ is required because the SeekableByteChannel supports both reading and writing.

Specifying READ opens the channel for reading. Specifying WRITE or APPEND opens the channel for writing. If none of these options are specified, then the channel is opened for reading.

The following code snippet reads a file and prints it to standard output:

The following example, written for UNIX and other POSIX file systems, creates a log file with a specific set of file permissions. This code creates a log file or appends to the log file if it already exists. The log file is created with read/write permissions for owner and read only permissions for group.

Methods for Creating Regular and Temporary Files

Creating Files

You can create an empty file with an initial set of attributes by using the createFile(Path, FileAttribute<?>) method. For example, if, at the time of creation, you want a file to have a particular set of file permissions, use the createFile method to do so. If you do not specify any attributes, the file is created with default attributes. If the file already exists, createFile throws an exception.

In a single atomic operation, the createFile method checks for the existence of the file and creates that file with the specified attributes, which makes the process more secure against malicious code.

The following code snippet creates a file with default attributes:

POSIX File Permissions has an example that uses createFile(Path, FileAttribute<?>) to create a file with pre-set permissions.

You can also create a new file by using the newOutputStream methods, as described in Creating and Writing a File using Stream I/O. If you open a new output stream and close it immediately, an empty file is created.

Creating Temporary Files

You can create a temporary file using one of the following createTempFile methods:

  • createTempFile(Path, String, String, FileAttribute<?>)
  • createTempFile(String, String, FileAttribute<?>)

The first method allows the code to specify a directory for the temporary file and the second method creates a new file in the default temporary-file directory. Both methods allow you to specify a suffix for the filename and the first method allows you to also specify a prefix. The following code snippet gives an example of the second method:

Как правильно записывать байты в файл java

Запись файлов и класс FileOutputStream

Класс FileOutputStream предназначен для записи байтов в файл. Он является производным от класса OutputStream, поэтому наследует всю его функциональность.

Через конструктор класса FileOutputStream задается файл, в который производится запись. Класс поддерживает несколько конструкторов:

Файл задается либо через строковый путь, либо через объект File. Второй параметр — append задает способ записи: eсли он равен true, то данные дозаписываются в конец файла, а при false — файл полностью перезаписывается

Например, запишем в файл строку:

Для создания объекта FileOutputStream используется конструктор, принимающий в качестве параметра путь к файлу для записи. Если такого файла нет, то он автоматически создается при записи. Так как здесь записываем строку, то ее надо сначала перевести в массив байтов. И с помощью метода write строка записывается в файл.

Для автоматического закрытия файла и освобождения ресурса объект FileOutputStream создается с помощью конструктции try. catch.

При этом необязательно записывать весь массив байтов. Используя перегрузку метода write() , можно записать и одиночный байт:

Чтение файлов и класс FileInputStream

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

Для создания объекта FileInputStream мы можем использовать ряд конструкторов. Наиболее используемая версия конструктора в качестве параметра принимает путь к считываемому файлу:

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

Считаем данные из ранее записанного файла и выведем на консоль:

В данном случае мы считываем каждый отдельный байт в переменную i:

Когда в потоке больше нет данных для чтения, метод возвращает число -1.

Затем каждый считанный байт конвертируется в объект типа char и выводится на консоль.

Подобным образом можно считать данные в массив байтов и затем производить с ним манипуляции:

В данном случае с помощью метода read() считываем данные в массив buffer длиной 256 байтов. Метод возвращает количество считанных байтов.

Поскольк файл может быть больше 256 байтов, то считываем в цикле while до конца файла. Когда больше не останется файлов для считывания, то метод возвратит -1.

Поскольку количество считанных байтов/размер файла могут быть меньше 256 байт, то реальное количество считанных байт сохраняем в переменную count. Затем выводим считанное количество данных на консоль в цикле for.

Совместим оба класса и выполним чтение из одного и запись в другой файл:

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

Запись данных в файлы на языке Java

Запись в файл — это поток данных, которым управляют классы выводного потока. На вершине дерева этих классов находится OutputStream, который содержит в себе дочерние классы управлением потока вывода байтов в файлы, консоль, сокеты и другое. Наследниками OutputStream являются следующие классы:

  • FileOutputStream (далее OS),
  • ObjectOS,
  • BufferedOS,
  • ByteArrayOS,
  • FilterOS,
  • DataOS.

Однако в рамках манипуляций с файловыми потоками, а точнее для записи символов, удобнее использовать стек классов из абстрактного класса Writer. Он специально разработан передачи строковых и символьных данных для записи в файлы и другие объекты. Он включает в себя следующие классы: CharArrayWriter, FileWriter, BufferedWriter, FilterWriter.

Запись байтов в файл

Запись байтов в файл осуществляется посредством создания объекта байтового потока класса FileOutputStream. Конструктор объекта предусматривает один параметр, который задает путь к файлу типа String.

Также в качестве пути можно вставить в конструктор объект типа File. Второй параметр не обязателен и является типом boolean. У него есть два значения: true — запись файла продолжается; false — имеющиеся данные в файле обнуляются и запись начинается с начала.

Читать:
Cisco anyconnect как пользоваться

Пример записи строки в файл:

class Example <
public static void Main() <
String t = «Don’t worry! We w’got everything we need.»; \\ Строка для записи в файл
FileOutputStreambyteFlow = new FileOutputStream(«note.txt», false); \\ Создаем объект потока к файлу note.txt
byte[] strToByte = t.getBytes(); \\ перевод строки в байты
byteFlow.write(strToByte); \\ Запись байтов в файл
t.close();
>
>

Задача программы — запись в файл «note.txt», который расположен в папке проекта строки «Don’tworry! Wew’goteverythingweneed.» в байтовом формате:

  1. Сохраняется в переменную «t» главная строка, которую планируется записать в текстовый файл.
  2. Открываем файловый поток созданием объекта класса FileOutputStream и ставим ему в качестве первого параметра путь к файлу, второй параметр указывает на то, что файл будет перезаписан.
  3. Переводим каждый символ строки в числовой формат и сохраняем его в массив символов.
  4. Записываем числовые байты в файл, которые автоматически конвертируются в символы и становятся первоначальной строкой.
  5. Закрываем поток.

Здесь есть один вопрос: Зачем записывать текстовые файлы в байтовом формате? Ведь язык Java имеет все необходимое для записи текстовых файлов. Байтовый поток требуется для графических, медиа-файлов. Для текстовых файлов предусмотрены отдельные классы и набор методов.

Класс FileWriter для записи текстовых файлов

FileWriter наследует весь функционал от верхнего в иерархии класса Writer. Конструктор объектов класса FileWriter может получать следующие параметры:

  1. Объект типа File.
  2. Строковой путь к файлу с его именем.
  3. Дескриптор файла типа FileDescriptor.

Второй параметр не обязателен. Его значения true или false, где первый вариант продолжает запись файла, а второй полностью перезаписывает его.

Пример записи текстового файла:

FileWritertxt_file = newFileWriter(C:\\docs\tf.txt, false);
txt_file.write(«Good morning!»);
txt_file.close();

В данном примере мы обошлись без форматирования строки в байты. Метод write(text) просто записывает строку в начало файла, поскольку в конструкторе выставлен параметр его перезаписи. Следует не забывать закрывать файловый поток с помощью метода close(). Это позволит экономно распоряжаться памятью и не перегружать приложение лишними активностями, которые возможно в дальнейшем не будут использоваться.

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

Методы для записи файлов через байтовый поток

Класс OutputStream передает своим потомкам следующие методы:

  1. write(byte[] b)- запись массива байтов в файл;
  2. write(byte[] b, intgoto, intlength) — записывает массив байтов в файл из первого параметра, второй параметр смещает каретку на int ступеней, третий параметр указывает количество записываемых байтов.
  3. write(intch) — записывает в файл лишь один байт в числовом формате, указанном в единственном параметре.
  4. close() — закрытие потока и очистка памяти.
  5. flush() — очистка буфера потока от одного или массива байтов.

Все данные методы ничего не возвращают. Поэтому, их возвращаемое значением по умолчанию является void.

Методы для манипуляций с текстовым потоком

Класс Writer предоставляет несколько методов для дочерних классов:

  1. write(char[] str) — запись строки в файл по символьно.
  2. write(Stringstr, intgoto, intlength) — запись строки со смещением каретки на goto символов вперед с ограниченной длиной строки length.
  3. Writerappend(CharSequencestr) — в конец файла записывается строка str, и возвращается объект Writer.
  4. close() — закрытие текстового потока.

Заключение

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

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

Rukovodstvo

статьи и идеи для разработчиков программного обеспечения и веб-разработчиков.

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

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

Время чтения: 8 мин.

Вступление

В этой статье мы углубимся в чтение и запись файлов на 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

  • это неблокирующий 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, представляющую путь к файлу в своих конструкторах. Вы также можете передать File а также FileDescriptor .

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

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

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

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

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

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

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

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

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

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

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

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

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

Заключение

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

Похожие статьи