Как правильно записывать байты в файл java
Класс FileOutputStream предназначен для записи байтов в файл. Он является производным от класса OutputStream, поэтому наследует всю его функциональность.
Через конструктор класса FileOutputStream задается файл, в который производится запись. Класс поддерживает несколько конструкторов:
FileOutputStream(String filePath) FileOutputStream(File fileObj) FileOutputStream(String filePath, boolean append) FileOutputStream(File fileObj, boolean append)
Файл задается либо через строковый путь, либо через объект File. Второй параметр — append задает способ записи: eсли он равен true, то данные дозаписываются в конец файла, а при false — файл полностью перезаписывается
Например, запишем в файл строку:
import java.io.*; public class Program < public static void main(String[] args) < String text = "Hello world!"; // строка для записи try(FileOutputStream fos=new FileOutputStream("notes.txt")) < // перевод строки в байты byte[] buffer = text.getBytes(); fos.write(buffer, 0, buffer.length); System.out.println("The file has been written"); >catch(IOException ex) < System.out.println(ex.getMessage()); >> >
Для создания объекта FileOutputStream используется конструктор, принимающий в качестве параметра путь к файлу для записи. Если такого файла нет, то он автоматически создается при записи. Так как здесь записываем строку, то ее надо сначала перевести в массив байтов. И с помощью метода write строка записывается в файл.
Для автоматического закрытия файла и освобождения ресурса объект FileOutputStream создается с помощью конструктции try. catch.
При этом необязательно записывать весь массив байтов. Используя перегрузку метода write() , можно записать и одиночный байт:
fos.write(buffer[0]); // запись первого байта
Чтение файлов и класс FileInputStream
Для считывания данных из файла предназначен класс FileInputStream , который является наследником класса InputStream и поэтому реализует все его методы.
Для создания объекта FileInputStream мы можем использовать ряд конструкторов. Наиболее используемая версия конструктора в качестве параметра принимает путь к считываемому файлу:
FileInputStream(String fileName) throws FileNotFoundException
Если файл не может быть открыт, например, по указанному пути такого файла не существует, то генерируется исключение FileNotFoundException .
Считаем данные из ранее записанного файла и выведем на консоль:
import java.io.*; public class Program < public static void main(String[] args) < try(FileInputStream fin=new FileInputStream("notes.txt")) < int i; while((i=fin.read())!=-1)< System.out.print((char)i); >> catch(IOException ex) < System.out.println(ex.getMessage()); >> >
В данном случае мы считываем каждый отдельный байт в переменную i:
while((i=fin.read())!=-1)Когда в потоке больше нет данных для чтения, метод возвращает число -1.
Затем каждый считанный байт конвертируется в объект типа char и выводится на консоль.
Подобным образом можно считать данные в массив байтов и затем производить с ним манипуляции:
import java.io.*; public class Program < public static void main(String[] args) < try(FileInputStream fin=new FileInputStream("notes.txt")) < byte[] buffer = new byte[256]; System.out.println("File data:"); int count; while((count=fin.read(buffer))!=-1)< for(int i=0; i> > catch(IOException ex) < System.out.println(ex.getMessage()); >> > В данном случае с помощью метода read() считываем данные в массив buffer длиной 256 байтов. Метод возвращает количество считанных байтов.
Поскольк файл может быть больше 256 байтов, то считываем в цикле while до конца файла. Когда больше не останется файлов для считывания, то метод возвратит -1.
while((count=fin.read(buffer))!=-1)Поскольку количество считанных байтов/размер файла могут быть меньше 256 байт, то реальное количество считанных байт сохраняем в переменную count. Затем выводим считанное количество данных на консоль в цикле for.
for(int i=0; iСовместим оба класса и выполним чтение из одного и запись в другой файл:
import java.io.*; public class Program < public static void main(String[] args) < try(FileInputStream fin=new FileInputStream("notes.txt"); FileOutputStream fos=new FileOutputStream("notes_new.txt")) < byte[] buffer = new byte[256]; int count; // считываем буфер while((count=fin.read(buffer))!=-1)< // записываем из буфера в файл fos.write(buffer, 0, count); >System.out.println("File has been written"); > catch(IOException ex) < System.out.println(ex.getMessage()); >> >Классы FileInputStream и FileOutputStream предназначены прежде всего для записи двоичных файлов, то есть для записи и чтения байтов. И хотя они также могут использоваться для работы с текстовыми файлами, но все же для этой задачи больше подходят другие классы.
Запись byte[] в файл на Java
В этом кратком руководстве мы изучим несколько различных способов записи массива байтов Java в файл. Мы начнем с самого начала, используя пакет Java IO. Далее мы рассмотрим пример с использованием Java NIO. После этого мы будем использовать Google Guava и Apache Commons IO.
2. Java ввод/вывод
Пакет Java IO существует со времен JDK 1.0 и предоставляет набор классов и интерфейсов для чтения и записи данных.
Давайте используем FileOutputStream для записи изображения в файл:
File outputFile = tempFolder.newFile("outputFile.jpg"); try (FileOutputStream outputStream = new FileOutputStream(outputFile)) outputStream.write(dataForWriting); >Мы открываем выходной поток в наш целевой файл, а затем мы можем просто передать наш byte[] dataForWriting в метод записи . Обратите внимание, что здесь мы используем блок try -with-resources , чтобы убедиться, что мы закрываем OutputStream в случае возникновения исключения IOException .
3. Java НИО
Пакет Java NIO был представлен в Java 1.4, а API файловой системы для NIO был представлен как расширение в Java 7. Java NIO использует буферизацию и не блокирует, тогда как Java IO использует блокирующие потоки. Синтаксис создания файловых ресурсов более краток в пакете java.nio.file .
Мы можем написать наш byte[] в одну строку, используя класс Files :
Files.write(outputFile.toPath(), dataForWriting);В нашем примере либо создается файл, либо усекается существующий файл и открывается для записи. Мы также можем использовать Paths.get("путь/к/файлу") или Paths.get("путь", "к", "файл") для создания пути , который описывает, где будет храниться наш файл. Путь — это собственный способ выражения путей в Java NIO.
Если нам нужно переопределить поведение при открытии файла, мы также можем предоставить OpenOption методу записи .
4. Google Гуава
Guava — это библиотека от Google, которая предоставляет множество типов для выполнения общих операций в Java, включая ввод-вывод.
Давайте импортируем Guava в наш файл pom.xml :
dependency> groupId>com.google.guavagroupId> artifactId>guavaartifactId> version>31.0.1-jreversion> dependency>4.1. Файлы гуавы
Как и в случае с пакетом Java NIO, мы можем записать наш byte[] в одну строку:
Files.write(dataForWriting, outputFile);Метод Guava Files.write также принимает необязательный OptionOptions и использует те же значения по умолчанию, что и java.nio.Files.write .
Однако здесь есть одна загвоздка: метод Guava Files.write помечен аннотацией @Beta . Согласно документации , это означает, что он может измениться в любое время, поэтому его не рекомендуется использовать в библиотеках.
Итак, если мы пишем проект библиотеки, мы должны рассмотреть возможность использования ByteSink .
4.2. БайтСинк
Мы также можем создать ByteSink для записи нашего byte[] :
ByteSink byteSink = Files.asByteSink(outputFile); byteSink.write(dataForWriting);ByteSink — это место назначения, в которое мы можем записывать байты. Он поставляет OutputStream в пункт назначения.
Если нам нужно использовать java.nio.files.Path или предоставить специальный OpenOption , мы можем получить наш ByteSink с помощью класса MoreFiles :
ByteSink byteSink = MoreFiles.asByteSink(outputFile.toPath(), StandardOpenOption.CREATE, StandardOpenOption.WRITE); byteSink.write(dataForWriting);5. Apache Commons IO
Apache Commons IO предоставляет некоторые общие файловые задачи.
Давайте импортируем последнюю версию commons-io :
dependency> groupId>commons-iogroupId> artifactId>commons-ioartifactId> version>2.11.0version> dependency>Теперь давайте напишем наш byte[] с помощью класса FileUtils :
FileUtils.writeByteArrayToFile(outputFile, dataForWriting);Метод FileUtils.writeByteArrayToFile похож на другие методы, которые мы использовали, в том, что мы даем ему файл , представляющий желаемое место назначения, и двоичные данные, которые мы записываем. Если наш целевой файл или любой из родительских каталогов не существует, они будут созданы.
6. Заключение
В этом коротком руководстве мы узнали, как записывать двоичные данные из byte[] в файл, используя обычную Java и две популярные служебные библиотеки Java: Google Guava и Apache Commons IO.
Как всегда, код примера доступен на GitHub .
- 1. Обзор
- 2. Java ввод/вывод
- 3. Java НИО
- 4. Google Гуава
- 4.1. Файлы гуавы
- 4.2. БайтСинк
Запись байта [] в файл в Java
«Преобразовать массив байтов в объект File» не имеет никакого смысла, кроме как в том, что вы хотите записать байты в файл. У вас есть как минимум 3 разных ответа ниже, как это сделать. Это то, что вы после? В противном случае, пожалуйста, уточните.
pap 26 июль 2011, в 11:14
Я разрабатываю в Android . У меня есть файл, сохраненный на диске в зашифрованном виде и разблокировать шифрование, поэтому я получил массив байтов, поэтому я хочу преобразовать их в файл, чтобы показать файл PDF в программе просмотра PDF, но без сохранения файла на диске без шифрования
farajnew 26 июль 2011, в 11:21
Ну, тогда это совсем другое. Вы хотите запустить pdf-просмотрщик, по сути, из чего-то вроде MemoryFile ( developer.android.com/reference/android/os/MemoryFile.html ). Не уверен, как вы это сделаете, или как вы отображаете PDF. У вас есть код или информация, которую вы можете добавить о том, как вы на самом деле вызываете программу просмотра PDF? А какой просмотрщик вы используете?
pap 26 июль 2011, в 12:17
Пожалуйста, измените вопрос и название, чтобы отразить тот факт, что вы спрашиваете о чем-то связанном с PDF. Вопрос выглядит пока запутанным.
Mike Keskinov 29 авг. 2012, в 16:22
-1 Вопрос совершенно не связан с тем, что ты хочешь знать. Создайте новый вопрос и задайте вопрос «Как я могу рендерить PDF на Android из байтов в памяти?»
Aaron Digulla 10 окт. 2012, в 13:25
Показать ещё 3 комментария
Поделиться:5 ответов
Лучший ответ
Объект File не содержит содержимого файла. Это только указатель на файл на вашем жестком диске (или другой носитель, например SSD, USB-накопитель, общий сетевой ресурс). Поэтому я думаю, что вы хотите записать его на жесткий диск.
Вы должны записать файл, используя некоторые классы в Java API
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(yourFile)); bos.write(fileBytes); bos.flush(); bos.close();Вы также можете использовать Writer вместо OutputStream. Использование записи позволит вам написать текст (String, char []).
BufferedWriter bw = new BufferedWriter(new FileWriter(yourFile));Поскольку вы сказали, что хотите сохранить все в памяти и не хотите ничего писать, вы можете попробовать использовать ByteArrayInputStream . Это имитирует InputStream, который вы можете передать большинству классов.
ByteArrayInputStream bais = new ByteArrayInputStream(yourBytes);Martijn Courteaux 26 июль 2011, в 10:44
ПоделитьсяФайловый объект является нулевым? и я не хочу, чтобы что-либо было сохранено на диске . Это нормально, чтобы быть в памяти, так как конвертировать массив байтов в объект File
farajnew 26 июль 2011, в 11:10
Я получил это java.io.IOException: открытие не удалось: EACCES (Отказано в доступе) в приложении для Android при записи BufferedOutputStream bos = new BufferedOutputStream (new FileOutputStream (yourFile));
Sanket Thakkar 02 авг. 2013, в 07:41
@SanketThakkar: Возможно, у вас нет прав на запись (разрешение) на запись файла в этом месте. Попробуйте другое место.
Преобразование массива байтов в файл в Java
В работе с Java часто возникают ситуации, когда необходимо записать массив байтов, представляющий собой файл, на диск. Например, это может быть необходимо при получении файла из сети в виде массива байтов, который нужно сохранить для дальнейшего использования.
В Java для решения этой задачи можно использовать классы из стандартной библиотеки, такие как FileOutputStream или Files .
Рассмотрим пример реализации с помощью FileOutputStream :
import java.io.FileOutputStream; import java.io.IOException; public class Main < public static void main(String[] args) < byte[] bytes = ; try (FileOutputStream fos = new FileOutputStream("myfile.pdf")) < fos.write(bytes); >catch (IOException e) < e.printStackTrace(); >> >В этом коде создается экземпляр FileOutputStream , который отвечает за запись в файл. Метод write этого класса записывает массив байтов в файл. Стоит обратить внимание на использование конструкции try-with-resources, которая автоматически закрывает поток записи после его использования.
Альтернативным вариантом является использование класса Files и его статического метода write .
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; public class Main < public static void main(String[] args) < byte[] bytes = ; try < Files.write(Paths.get("myfile.pdf"), bytes); >catch (IOException e) < e.printStackTrace(); >> >В этом примере метод write класса Files принимает путь к файлу и массив байтов для записи. В отличие от FileOutputStream , этот метод самостоятельно открывает, записывает и закрывает файл.
Оба этих варианта позволяют записать массив байтов в файл на диске, выбор между ними зависит от конкретных требований и предпочтений.
