Запись 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. БайтСинк
Как перевести файл в массив байтов
Как перевести файл в массив байтов и наоборот? Файлом может быть MS Word и Excel или что-то другое. Также и строку.
Отслеживать
user177221
задан 7 сен 2015 в 3:48
Aslan Kussein Aslan Kussein
1,776 2 2 золотых знака 14 14 серебряных знаков 35 35 бронзовых знаков3 ответа 3
Сортировка: Сброс на вариант по умолчанию
byte[] array = Files.readAllBytes(Paths.get(fileName));
Отслеживать
5,509 16 16 серебряных знаков 42 42 бронзовых знака
ответ дан 7 сен 2015 в 7:33
465 3 3 серебряных знака 13 13 бронзовых знаковbyte[] fileInArray = new byte[(int)file.length()]; FileInputStream f = new FileInputStream(""); f.read(fileInArray);
Это без использования всякого рода сторонних библиотек. Средствами java.
Отслеживать
ответ дан 7 сен 2015 в 4:18
Виталий Вихляев Виталий Вихляев
891 15 15 серебряных знаков 34 34 бронзовых знака\я вот если я пытаюсь из джава класса сделать массив байтов и какой метод мне использовать не знаете?
7 сен 2015 в 4:28
@Aslan Kussein с файлами .java точно так же. Если же вам нужно в массив байтов преобразовать объект какого-то класса , то вам необходимо его сериализовать. Очень хороший ресурс на эту тему здесь
7 сен 2015 в 4:56
А вы документацию к InputStream.read читали? Там вообще-то написано «Reads some number of bytes from the input stream and stores them into the buffer array b». А вы даже возвращаемое значение не проверяете. Чтение может прерваться в произвольный момент, и вы никак не узнаете, сколько байт считано по факту.
7 сен 2015 в 6:20
@Tagir Valeev никто не мешает обработать ошибку при чтении. Насчет контроля количества считанных байт согласен- в моем способе его нет (а может и не нужен). И все же. Как вы решали бы эту проблему, при использовании java более взрослых версий?
7 сен 2015 в 7:10
Вообще, вероятно, лучше memory-mapping сделать. Это будет быстрее. Если без мемори-мэппинга — воспользовался бы библиотекой или написал бы вручную примерно то же самое, что в readAllBytes .
Выполнить чтение всех байтов с файла с помощью FileInputStream в массив байтов
Выполнить чтение всех байтов с файла с помощью FileInputStream в массив байтов.
Создать строку на основе прочитанного массива байтов и после этого выполнить String.trim().
Разделить полученную строку таким образом, чтобы создать экземпляры классов(String.split).
Так же, реализовать запись в файл в соответствующем формате.
Вот мой массив и собственно запись —
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
public static void main(String[] args) { Car[] taxiPark = new Car[]{ new Truck("Reno", 65000, 20, 180, 25000), new Truck("Scania", 100000, 15, 220, 30000), new MilitaryVehicles("T-34", 85000, 50, 35, 5), new MilitaryVehicles("T-190", 120000, 70, 60, 10), new PassengerCar("Lanos", 5000, 6, 225, 4), new PassengerCar("BMW", 10000, 9, 300, 5) }; try (final FileWriter writer = new FileWriter("Letter.txt", false)){ for (int i = 0; i taxiPark.length; ++i) { final String s = taxiPark[i].toString(); writer.write(s); writer.write(System.lineSeparator()); System.out.println(s); } } catch(IOException e) { System.out.println(e.getMessage()); } }
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:Чтение байтов из файла
Здравсвуйте! Есть файл в котором записвны числа 1234567890. Есть такой код int amount, sum = 0; .Чтение группы байтов из файла
Необходимо прочитать 4 байта из двоичного файла. Открываю файл и ставлю указатель в нужное место.Чтение и запись байтов из файла
Подскажите пожалуйста каким образом магу прочесть .дат файл чтобы прочесть байты и обратно.Чтение байтов из бинарного файла
Доброго времени суток. Столкнулся с задачкой которую не могу правильно решить. Вообщем к сути.746 / 493 / 285
Регистрация: 10.09.2015
Сообщений: 1,530Добавлено через 1 минуту
и при чём тут машины?Добавлено через 7 минут
покажи как файл у тебя записываетсяДобавлено через 49 секунд
всёс виду выглядит очень простоРегистрация: 28.02.2019
Сообщений: 11Смотри, у меня есть таксипарк, от него наследуются машины разных видов(каждый со своей особенностью), отдельно есть класс таксипарка, в котором выполняются определенные функции, вот в меине мне нужно записать этот массив в файл потом выполнить чтение всех байтов.
Вот полное задание — Реализовать инициализацию массива Car’ов (из задания про таксопарк) на основе файла (машины должны храниться в файле).Запятая (,) — разделитель свойств машины
Точка с запятой и конец строки (;\n\r) — разделитель машин
Выполнить чтение всех байтов с файла с помощью FileInputStream в массив байтов.
Создать строку на основе прочитанного массива байтов и после этого выполнить String.trim().
Разделить полученную строку таким образом, чтобы создать экземпляры классов(String.split).
Так же, реализовать запись в файл в соответствующем формате.
746 / 493 / 285
Регистрация: 10.09.2015
Сообщений: 1,530toString() покажи, пжл
Добавлено через 4 минуты
в общем вот чтение файла:1 2 3 4 5 6 7 8 9 10 11
private static String readFile(String path) { String result = null; try (FileInputStream in = new FileInputStream(new File(path))) { byte[] buffer = new byte[in.available()]; in.read(buffer, 0, buffer.length); result = new String(buffer); } catch (IOException e) { e.printStackTrace(); } return result; }
Добавлено через 2 минуты
коли ты записываешь строки через System.lineSeparator();то делишь потом текст из файла на строковое представление объекта
String[] cars = string.split(System.lineSeparator()); //string — это то, что вернулось из метода чтения файла
Регистрация: 28.02.2019
Сообщений: 11Вот to.String Такси парка —
public String toString() return «TaxiParkInter «taxiPark = » + Arrays.toString(taxiPark) +
‘>’;
>А вот отдельной машины(to.String определен в каждом классе) —
public String toString() return «MilitaryVehicles » Max Speed = » + getMaxSpeed() +
» LevelOfDestruction = » + LevelOfDestruction +
‘>’;
>746 / 493 / 285
Регистрация: 10.09.2015
Сообщений: 1,530затем, почитай про паттерн Factory. Он как раз для создания фабрик.
у тебя там и танки и машины и т.д.
вот и будешь передавать параметром в метод типа «tank», а он тебе возвращать объект типа tankДобавлено через 5 минут
переделай метод toString() как просят записывать файл (через запятые)
проще делить будет строку на поля объекта по запятой:1 2 3 4 5
for (String car : string.split(System.lineSeparator()) { String[] values = car.split(","); //сделаешь метод, который принимает массив values и парсит его в объект //а затем в метод Factory.build(String type) передашь тип и поля и он тебе вернёт нужный класс }
Добавлено через 4 минуты
имя класса можно получить:this.getClass().getCanonicalName()
Регистрация: 28.02.2019
Сообщений: 11
Спасибо, посижу поломаю голову, пока что правда не все понял=)) Но очень благодарен
746 / 493 / 285
Регистрация: 10.09.2015
Сообщений: 1,530LexusJava, если не получится, завтра ближе к вечеру смогу помочь тебе. А сейчас, ксожалению, спать мне нужно. Если что пиши и удачи с кодом или до завтра
Регистрация: 28.02.2019
Сообщений: 11
Большое спасибо, буду иметь ввиду, Доброй ночи
Регистрация: 12.05.2019
Сообщений: 201как ни странно но у меня тот же самый вопрос и написанное выше никак не помогло(((
застряла на этапе «Разделить полученную строку таким образом, чтобы создать экземпляры классов(String.split).»
вот что у меня есть
Car[] cars = storage.readCars();
1 2 3 4 5 6 7 8 9 10 11
public Car[] readCars() throws IOException { FileInputStream fis = new FileInputStream(text.txt); byte[] readBytes = new byte[fis.available()]; fis.read(readBytes); String file = new String(readBytes); System.out.println(Arrays.toString(file.split(";\r\n"))); String[] fieldCar; fieldCar = file.split(","); fis.close(); return cars; /////// . }
байты прочитаны, получен массив строк fieldCar где все поля(строки) лежат через запятую. Но как теперь разложить это по обьектам бьюсь сутки(( не понимаю.
условие тоже самое что у топикстартера
1021 / 561 / 185
Регистрация: 18.08.2013
Сообщений: 2,026
Записей в блоге: 2
Sma6nta, как выглядят конструкторы создаваемых объектов?
Регистрация: 12.05.2019
Сообщений: 201это хороший вопрос.
я на него с утра пытаюсь ответить.были конструкторы. нормальные
имя- стринг
int
int
и т.п. гетеры сетеры.создавались обьекты
car[0] = new MyCar(«Giguli», 12, 38, 25, 3);и отлично создавались. но теперь я пытаюсь считать с файла.
А оно там когда из байтов преобразуется то все Stringя пыталась создать новый конструктор
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
public class CarMaker implements Car{ private String mark; private String model; private String fuelConsumption; private String speed; private String price; private String typecar; public CarMaker(String mark, String model, String fuelConsumption, String speed, String price, String typecar) { this.mark = mark; this.model =model; this.fuelConsumption =fuelConsumption; this.speed = speed; this.price = price; this.typecar=typecar; } @Override public String getMark() { // TODO Auto-generated method stub return null; } @Override public void setMark() { // TODO Auto-generated method stub } @Override public int getModel() { // TODO Auto-generated method stub return 0; } @Override public void setModel() { // TODO Auto-generated method stub } @Override public int getFuelConsumption() { // TODO Auto-generated method stub return 0; } @Override public void setFuelConsumption() { // TODO Auto-generated method stub } @Override public int getSpeed() { // TODO Auto-generated method stub return 0; } @Override public void setSpeed() { // TODO Auto-generated method stub } @Override public int getPrice() { // TODO Auto-generated method stub return 0; } @Override public void setPrice() { // TODO Auto-generated method stub } @Override public String getTypeCar() { // TODO Auto-generated method stub return null; } @Override public void setTypeCar() { // TODO Auto-generated method stub } }
Чтение и запись файлов
В Java есть четыре основных абстрактных класса, реализующих потоки ввода-вывода: InputStream, OutputStream, Reader, Writer. Первые два работают с байтами, вторые – с символами.
Для работы с файлами от этих абстрактных классов созданы соответственно классы FileInputStream, FileOutputStream, FileReader, FileWriter. Они являются адаптерами для объектов класса File к «интерфейсам» InputStream, OutputStream, Reader, Writer, т. е. к их методам.
Скажем несколько слов об адаптере как паттерне, или шаблоне, проектирования. Класс-адаптер A наследуется от интерфейса B, к которому приспосабливается объект другого класса – C. Класс-адаптер A имеет поле типа класса объекта C.
Например, объект File адаптируется к потоку ввода InputStream, т. е. все, что мы хотим получить из File, в конечном итоге мы будем получать из InputStream. Фактически мы работаем с InputStream, через адаптер FileInputStream, который с одной стороны наследуется от InputStream, а с другой – имеет поле, которому присваивается объект File.
Адаптер выполняет работу по получению данных из файла и адаптации их к тому виду, который можно передать в методы InputStream. Класс-адаптер, в данном примере – FileInputStream, переопределяет методы InputStream, добавляя в них свой код.
В основной ветке сначала создается объект, для которого требуется адаптер. Затем создается переменная класса, к которому выполняется адаптация. Этой переменной присваивается объект класса-адаптера, в конструктор которого передается адаптируемый объект.
File file = new File("/home/user/pic.jpg"); InputStream fIn = new FileInputStream(file);
Часто переменную определяют самим классом-адаптером:
FileInputStream fIn = new FileInputStream(file);
В конструктор можно передать строку-адрес. Объект File будет создан внутри адаптера. Пример побайтового копирования файла:
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class InputOutputStream public static void main(String[] args) throws IOException FileInputStream fileIn = new FileInputStream( "src/file/pets.png"); FileOutputStream fileOut = new FileOutputStream( "src/file/pets2.png"); while (fileIn.available() > 0) int oneByte = fileIn.read(); fileOut.write(oneByte); > fileIn.close(); fileOut.close(); > >
Если используются относительные адреса, они должны начинаться от корня проекта.
В конструктор FileOutputStream можно также передать второй аргумент true. В этом случае, если файл существует, данные в него будут добавляться. Перезаписи файла не произойдет.
Метод available() объекта класса FileInputStream возвращает количество непрочитанных байтов. Метод read() читает один байт и расширяет его до типа int. Кроме этого, есть другой метод read(), читающий массив байт в переменную-аргумент и возвращающий количество реально прочитанных байт. Метод write() также позволяет записывать блоками.
byte[] blockBytes = new byte[100]; while (fileIn.available() > 0) int qtyBytes = fileIn.read(blockBytes); fileOut.write(blockBytes, 0, qtyBytes); >
При чтении конца файла блок может содержать меньше прочитанных байт, чем размерность массива. Поэтому write() позволяет указывать срез массива.
У объектов FileOutputStream имеется метод flush(), который принудительно записывает находящиеся в буфере байты на диск. При вызове close() это происходит автоматически.
С помощью класса PrintStream также можно создать поток вывода в файл. PrintStream является наследником FilterOutputStream, который в свою очередь наследник OutputStream как и FileOutputStream.
import java.io.FileNotFoundException; import java.io.PrintStream; public class PrintStreamTest public static void main(String[] args) throws FileNotFoundException PrintStream fileOut = new PrintStream( "src/file/text.txt"); fileOut.println(10.5); fileOut.printf( "%s - %d - %f", "hi", 10, 1.1); fileOut.close(); > >
Функция printf() предназначена для форматированного вывода.
Заметим, переменная System.out является объектом типа PrintStream.
В работе с вводом-выводом также используется другой паттерн проектирования – обертка (wrapper), он же декоратор (decorator). Декоратор расширяет функциональность объекта, а не приспосабливает объект к какому-либо стороннему интерфейсу.
Поэтому класс-обертка наследуется от того же класса или интерфейса, что и оборачиваемый объект. В классе-обертке переопределяются методы оборачиваемого объекта. В методах обертки вызываются методы оборачиваемого класса и вводится дополнительная функциональность.
В основной ветке создается объект оборачиваемого класса, который передается в конструктор обертки. Внутри класса-обертки есть поле типа декорируемого класса. Этому полю присваивается переданный объект.
BufferedInputStream – класс-обертка для InputStream (наследует через FilterInputStream). В отличие от InputStream класс BufferedInputStream позволяет предварительно читать в буфер порции байт, что уменьшает количество обращений к файлу. Существует также BufferedOutputStream.
import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; public class BufferStream public static void main(String[] args) throws IOException FileInputStream fileIn = new FileInputStream("src/file/text.txt"); BufferedInputStream bufIn = new BufferedInputStream(fileIn, 100); int i; while((i = bufIn.read())!= -1) System.out.print((char)i); > > >
Конструктор класса BufferedInputStream принимает объект InputStream или его наследника.
Хотя данные считываются блоками, метод read() извлекает их по одному. Однако в данном случае он будет извлекать их из буфера.
С помощью классов FileReader и FileWriter выполняется ввод-вывод в текстовые файлы.
FileReader reader = new FileReader( "src/file/text.txt"); FileWriter writer = new FileWriter( "src/file/text2.txt"); while (reader.ready()) int c = reader.read(); writer.write(c); > reader.close(); writer.close();
Метод ready() возвращает истину, если остались непрочитанные символы.
Читать и писать можно блоками. Также методу write() можно передать строку:
FileReader reader = new FileReader( "src/file/text.txt"); FileWriter writer = new FileWriter( "src/file/text3.txt"); char[] buff = new char[10]; while (reader.ready()) int qtySymbols = reader.read(buff); writer.write(buff, 0, qtySymbols); > writer.write("Halo"); reader.close(); writer.close();
Рассматривая ввод данных с клавиатуры, мы уже использовали класс BufferedReader, который наследуется от Reader и позволяет читать отдельные строки методом readLine(). Его также можно использовать для построчного чтения файлов:
import java.io.*; public class BufferedReaderTest public static void main(String[] args) throws IOException Reader reader = new FileReader( "src/file/text.txt"); BufferedReader buffReader = new BufferedReader(reader); while (buffReader.ready()) System.out.println( buffReader.readLine()); > reader.close(); buffReader.close(); > >
Существует и BufferedWriter.
X Скрыть Наверх
Программирование на Java. Курс