Внутренне это создает ByteArrayOutputStreamи копирует байты в вывод, а затем вызывает toByteArray(). Он обрабатывает большие файлы, копируя байты в блоки по 4 КБ.
Если вы хотите написать 4 строки кода, считаете ли вы целесообразным импортировать сторонние зависимости?
oxbow_lakes
217
Если есть библиотека, которая обрабатывает требование, занимается обработкой больших файлов и хорошо протестирована, то, конечно, вопрос в том, зачем мне ее писать? Емкость составляет всего 107 КБ, и если вам нужен один метод из этого, вы, вероятно, будете использовать и другие
Rich Seller
242
@oxbow_lakes: учитывая ошеломляющее количество неправильных реализаций этой функции, которые я видел в своей жизни разработчика, я чувствую, что да, это очень стоит внешней зависимости, чтобы сделать это правильно.
Иоахим Зауэр
17
Почему бы не пойти и взглянуть на такие вещи, как Apache Commons FastArrayListили их мягкие и слабые справочные карты, и вернуться и рассказать мне, насколько «хорошо проверена» эта библиотека. Это куча мусора
oxbow_lakes
87
В дополнение к Apache commons-io, проверьте класс ByteStreams из Google Guava . InputStream is;byte[] filedata=ByteStreams.toByteArray(is);
michaelok
446
Вам нужно прочитать каждый байт из вашего InputStreamи записать его в ByteArrayOutputStream.
Затем вы можете получить базовый байтовый массив, вызвав toByteArray():
InputStream is =...ByteArrayOutputStream buffer =newByteArrayOutputStream();int nRead;byte[] data =newbyte[16384];while((nRead = is.read(data,0, data.length))!=-1){
buffer.write(data,0, nRead);}return buffer.toByteArray();
Как насчет размера вновь созданного байта []. Почему это 16384? Как я могу определить точный правильный размер? Большое спасибо.
Ондрей Бозек
6
16384 - довольно произвольный выбор, хотя я склоняюсь к степени 2, чтобы увеличить вероятность выравнивания массива по границам слова. Ответ pihentagy показывает, как можно избежать использования промежуточного буфера, а лучше выделить массив правильного размера. Если вы не имеете дело с большими файлами, я лично предпочитаю приведенный выше код, который является более элегантным и может использоваться для InputStreams, где число байтов для чтения заранее неизвестно.
Адамски
@ Adamski Не создает ли массив байтов больше, чем вы ожидаете, данные будут в потоке, тратить впустую память?
Павел Бревчински
@bluesm: Да, это правильно. Тем не менее, в моем примере размер массива байтов составляет всего 16 КБ, и он настолько мал по современным стандартам. Кроме того, конечно, эта память будет освобождена снова после этого.
Адамски
5
@ Adamski Многие инфраструктурные аппаратные средства, веб-серверы и компоненты уровня ОС используют 4K-буферы для перемещения данных, поэтому это точное значение, но главное в том, что вы получаете такое небольшое повышение производительности, переходя на 4K что это обычно считается расточительством памяти. Я предполагаю, что это все еще верно, потому что это десятилетние знания, которые я имел!
312
Наконец, через двадцать лет, благодаря Java 9 , существует простое решение без необходимости использования сторонней библиотеки :
+1 за использование стандартных библиотек вместо сторонней зависимости. К сожалению, это не работает для меня, потому что я не знаю длину потока заранее.
Эндрю Спенсер
2
что такое imgFile? Это не может быть InputStream, который должен был быть вводом этого метода
Янус Троелсен
4
@janus это "Файл". этот способ работает, только если вы знаете длину файла или количество байтов для чтения.
Дермориц
5
Интересная вещь, но вы должны знать точную длину (части) потока для чтения. Более того, этот класс DataInputStreamиспользуется в основном для чтения первичных типов (Longs, Shorts, Chars ...) из потока, поэтому мы можем рассматривать это использование как неправильное использование класса.
Оливье Фошо
17
Если вы уже знаете длину данных для чтения из потока, это не лучше, чем InputStream.read.
Логан Пикап
119
Если вы используете Google Guava , это будет так просто, как:
Как и большинство других, я хотел избежать использования сторонней библиотеки для чего-то такого простого, но Java 9 на данный момент не подходит ... к счастью, я уже использовал Spring.
Скоттиссей
42
publicstaticbyte[] getBytesFromInputStream(InputStream is)throwsIOException{ByteArrayOutputStream os =newByteArrayOutputStream();byte[] buffer =newbyte[0xFFFF];for(int len = is.read(buffer); len !=-1; len = is.read(buffer)){
os.write(buffer,0, len);}return os.toByteArray();}
Это пример, и как таковая, краткость - это порядок дня. Также возвращение null здесь будет правильным выбором в некоторых случаях (хотя в производственной среде у вас также будет надлежащая обработка исключений и документация).
11
Я понимаю краткость в примере, но почему бы просто не заставить метод примера выбросить IOException, а не проглотить его и вернуть бессмысленное значение?
pendor
4
я
позволил себе
3
Попробовать с ресурсами здесь не нужно, потому что ByteArrayOutputStream # close () ничего не делает. (ByteArrayOutputStream # flush () не нужен и тоже ничего не делает.)
Люк Хатчисон,
25
Безопасное решение (с возможностьюcloseпотокового воспроизведения):
@Throws(IOException::class)
fun InputStream.readAllBytes():ByteArray{
val bufLen =4*0x400// 4KB
val buf =ByteArray(bufLen)
var readLen:Int=0ByteArrayOutputStream().use { o ->this.use { i ->while(i.read(buf,0, bufLen).also { readLen = it }!=-1)
o.write(buf,0, readLen)}return o.toByteArray()}}
Не означает ли это, что в какой-то момент вы удвоили бы используемую память, потому что у вас есть и буфер, и байтовый массив? Разве нет способа отправить байты напрямую в выходной байтовый массив?
Android разработчик
@androiddeveloper; Мне жаль. Я не знаю ответа! Но я так не думаю. Я думаю, что этот способ (с использованием буфера) является оптимизированным способом.
Мир Исмаили
Я проверил, и это так, но кажется, что это единственное решение, которое вы можете выбрать, когда вы не знаете размер. Если вы уже знаете размер, вы можете напрямую создать байтовый массив с заданным размером и заполнить его. Итак, вы используете функцию, которая получит параметр размера байта, и, если он действителен, используйте его для непосредственного создания и заполнения байтового массива, не создавая никаких других больших объектов.
Android-разработчик
@androiddeveloper; Спасибо за Вашу информацию. Я их не знал.
Мир Исмаили
19
Вам действительно нужно изображение как byte[]? Что именно вы ожидаете вbyte[] - полного содержимого файла изображения, закодированного в любом формате, в котором находится файл изображения, или значений пикселей RGB?
Другие ответы здесь показывают, как прочитать файл в byte[]. Ваш byte[]файл будет содержать точное содержимое файла, и вам потребуется его расшифровать, чтобы что-нибудь сделать с данными изображения.
Стандартный API Java для чтения (и записи) изображений - это API ImageIO, который вы можете найти в пакете javax.imageio. Вы можете прочитать изображение из файла с помощью одной строки кода:
Это даст вам, а BufferedImageне byte[]. Чтобы получить данные изображения, вы можете позвонить getRaster()на BufferedImage. Это даст вам Rasterобъект, который имеет методы доступа к данным пикселя (она имеет несколько getPixel()/ getPixels()методов).
Lookup документацию API для javax.imageio.ImageIO, java.awt.image.BufferedImage, и java.awt.image.Rasterт.д.
ImageIO по умолчанию поддерживает несколько форматов изображений: JPEG, PNG, BMP, WBMP и GIF. Можно добавить поддержку большего количества форматов (вам понадобится плагин, который реализует интерфейс поставщика услуг ImageIO).
Скажите, а что, если байтовый массив слишком велик, что может привести к OOM для кучи? Есть ли подобное решение, которое будет использовать JNI для хранения байтов, и позже мы сможем использовать inputStream из данных, хранящихся там (вроде временного кэша)?
разработчик Android
14
Если вы не хотите использовать библиотеку Apache commons-io, этот фрагмент взят из класса sun.misc.IOUtils. Это почти в два раза быстрее, чем обычная реализация, использующая ByteBuffers:
Это немного странное решение, длина - это верхняя граница длины массива. Если вы знаете длину, вам нужно только: byte [] output = new byte [length]; is.read (выход); (но смотрите мой ответ)
Люк Хатчисон
@ luke-hutchison, как я уже сказал, это решение sun.misc.IOUtils. В наиболее распространенных случаях вы не знаете размер входного потока InputStream, поэтому if (length == -1) length = Integer.MAX_VALUE; применяется. Это решение работает, даже если заданная длина больше, чем длина InputStream.
Кристиан Кральич,
@LukeHutchison Если вы знаете длину, вы можете обработать ее несколькими строками. Если вы посмотрите на каждый ответ, все будут жаловаться, что длина неизвестна. Наконец, ответ, который является стандартным, может использоваться с Java 7 Android, и не требует никакой внешней библиотеки.
Чаба Тот
11
ByteArrayOutputStream out =newByteArrayOutputStream();byte[] buffer =newbyte[1024];while(true){int r = in.read(buffer);if(r ==-1)break;
out.write(buffer,0, r);}byte[] ret = out.toByteArray();
// Returns the contents of the file in a byte array.publicstaticbyte[] getBytesFromFile(File file)throwsIOException{InputStream is =newFileInputStream(file);// Get the size of the filelong length = file.length();// You cannot create an array using a long type.// It needs to be an int type.// Before converting to an int type, check// to ensure that file is not larger than Integer.MAX_VALUE.if(length >Integer.MAX_VALUE){// File is too large}// Create the byte array to hold the databyte[] bytes =newbyte[(int)length];// Read in the bytesint offset =0;int numRead =0;while(offset < bytes.length
&&(numRead=is.read(bytes, offset, bytes.length-offset))>=0){
offset += numRead;}// Ensure all the bytes have been read inif(offset < bytes.length){thrownewIOException("Could not completely read file "+file.getName());}// Close the input stream and return bytes
is.close();return bytes;}
Конечно, но они должны знать размер: «Я хочу прочитать изображение»
pihentagy
1
Если вы знаете размер, то Java предоставляет код для вас. см. мой ответ или Google для "DataInputStream", и это метод readFully.
dermoritz
Вы должны добавить, is.close()если offset < bytes.lengthили InputStreamне будет закрыто, если выдается это исключение.
Джаред Раммлер
3
Тогда лучше использовать
пробную версию
8
InputStream is ...ByteArrayOutputStream bos =newByteArrayOutputStream();int next = in.read();while(next >-1){
bos.write(next);
next = in.read();}
bos.flush();byte[] result = bos.toByteArray();
bos.close();
Однако, как правило, операционная система уже достаточно буферизирует, чтобы не беспокоиться о файлах меньшего размера. Не то, чтобы головка жесткого диска считывала каждый байт отдельно (жесткий диск - это вращающаяся стеклянная пластинка с магнитной кодированной информацией, немного похожая на странный значок, который мы используем для сохранения данных: P).
Мартен Бодевес
6
@Maarten Bodewes: большинство устройств имеют своего рода передачу блоков, поэтому не каждое чтение () действительно вызывает фактический доступ к устройству, но наличие OS-вызова на байт уже достаточно для снижения производительности. В то время как упаковка InputStreamвBufferedInputStream коде до этого уменьшит количество вызовов ОС и значительно уменьшит недостатки производительности, этот код все равно будет выполнять ненужное ручное копирование из одного буфера в другой.
В чем разница между этим и InputStram.readAllBytes()одним?
Слава
2
Я знаю, что уже слишком поздно, но я думаю, что это более чистое решение, которое более читабельно ...
/**
* method converts {@link InputStream} Object into byte[] array.
*
* @param stream the {@link InputStream} Object.
* @return the byte[] array representation of received {@link InputStream} Object.
* @throws IOException if an error occurs.
*/publicstaticbyte[] streamToByteArray(InputStream stream)throwsIOException{byte[] buffer =newbyte[1024];ByteArrayOutputStream os =newByteArrayOutputStream();int line =0;// read bytes from stream, and store them in bufferwhile((line = stream.read(buffer))!=-1){// Writes bytes from byte array (buffer) into output stream.
os.write(buffer,0, line);}
stream.close();
os.flush();
os.close();return os.toByteArray();}
Это не просто \rпроблема. Этот метод преобразует байты в символы и обратно (используя набор символов по умолчанию для InputStreamReader). Любые байты, которые недопустимы в кодировке символов по умолчанию (скажем, -1 для UTF-8 в Linux), будут повреждены, что может даже изменить количество байтов.
Сеанф
Похоже, это хороший ответ, но ориентированный на текст. Покупатель, будь осторожен.
Wheezil
1
Я попытался отредактировать ответ @ numan с исправлением для записи мусорных данных, но редактирование было отклонено. Хотя этот короткий кусок кода не является чем-то блестящим, я не вижу другого лучшего ответа. Вот что имеет для меня наибольшее значение:
ByteArrayOutputStream out =newByteArrayOutputStream();byte[] buffer =newbyte[1024];// you can configure the buffer sizeint length;while((length = in.read(buffer))!=-1) out.write(buffer,0, length);//copy streams
in.close();// call this in a finally blockbyte[] result = out.toByteArray();
Кстати, ByteArrayOutputStream не нужно закрывать. конструкции try / finally опущены для удобства чтения
Особенно важно понимать, что вы не должны использовать этот метод для определения размера контейнера и предположить, что вы можете прочитать весь поток без необходимости изменять размер контейнера. Такие вызывающие абоненты, вероятно, должны записывать все, что они читают, в ByteArrayOutputStream и преобразовывать это в байтовый массив. В качестве альтернативы, если вы читаете из файла, File.length возвращает текущую длину файла (хотя допущение, что длина файла не может быть изменена, может быть неправильным, чтение файла по своей природе является довольно редким).
Оберните его в DataInputStream, если он по какой-то причине не находится на столе, просто используйте read, чтобы забить его, пока он не даст вам -1 или весь запрашиваемый блок.
Мы наблюдаем некоторую задержку для нескольких транзакций AWS при преобразовании объекта S3 в ByteArray.
Примечание. Объект S3 - это документ PDF (максимальный размер - 3 МБ).
Мы используем параметр # 1 (org.apache.commons.io.IOUtils) для преобразования объекта S3 в ByteArray. Мы заметили, что S3 предоставляет встроенный метод IOUtils для преобразования объекта S3 в ByteArray, мы просим вас подтвердить наилучший способ преобразования объекта S3 в ByteArray, чтобы избежать задержки.
Опция 1:
import org.apache.commons.io.IOUtils;
is = s3object.getObjectContent();
content =IOUtils.toByteArray(is);
Вариант № 2:
import com.amazonaws.util.IOUtils;
is = s3object.getObjectContent();
content =IOUtils.toByteArray(is);
Также дайте мне знать, если у нас есть какой-либо другой лучший способ преобразовать объект s3 в bytearray
Другой случай получить правильный байтовый массив через поток после отправки запроса на сервер и ожидания ответа.
/**
* Begin setup TCP connection to PC app
* to open integrate connection between mobile app and pc app (or mobile app)
*/
mSocket =newSocket(IP, port);// mSocket.setSoTimeout(30000);DataOutputStream mDos =newDataOutputStream(mSocket.getOutputStream());String str ="MobileRequest#"+ params[0]+"#<EOF>";
mDos.write(str.getBytes());try{Thread.sleep(1000);}catch(InterruptedException e){
e.printStackTrace();}/* Since data are accepted as byte, all of them will be collected in the
following byte array which initialised with accepted data length. */DataInputStream mDis =newDataInputStream(mSocket.getInputStream());byte[] data =newbyte[mDis.available()];// Collecting data into byte arrayfor(int i =0; i < data.length; i++)
data[i]= mDis.readByte();// Converting collected data in byte array into String.String RESPONSE =newString(data);
Вы делаете дополнительную копию, если используете ByteArrayOutputStream. Если вы знаете длину потока до того, как начнете его читать (например, InputStream на самом деле является FileInputStream, и вы можете вызвать file.length () для файла, или InputStream является записью в файле zipfile InputStream, и вы можете вызвать zipEntry. length ()), тогда гораздо лучше записать непосредственно в массив byte [] - он использует половину памяти и экономит время.
// Read the file contents into a byte[] arraybyte[] buf =newbyte[inputStreamLength];int bytesRead =Math.max(0, inputStream.read(buf));// If needed: for safety, truncate the array if the file may somehow get// truncated during the read operationbyte[] contents = bytesRead == inputStreamLength ? buf
:Arrays.copyOf(buf, bytesRead);
Обратите внимание, что последняя строка выше относится к файлам, усеченным во время чтения потока, если вам нужно обработать эту возможность, но если файл становится длиннее во время чтения потока, содержимое массива byte [] не будет удлиняться чтобы включить новое содержимое файла, массив будет просто урезан до старой длины inputStreamLength .
Добавьте некоторое объяснение с ответом о том, как этот ответ помогает ОП в исправлении текущей проблемы
ρяσѕρєя K
0
Это моя версия для копирования и вставки:
@SuppressWarnings("empty-statement")publicstaticbyte[] inputStreamToByte(InputStream is)throwsIOException{if(is ==null){returnnull;}// Define a size if you have an idea of it.ByteArrayOutputStream r =newByteArrayOutputStream(2048);byte[] read =newbyte[512];// Your buffer size.for(int i;-1!=(i = is.read(read)); r.write(read,0, i));
is.close();return r.toByteArray();}
Хотя этот фрагмент кода может решить вопрос, в том числе объяснение действительно помогает улучшить качество вашего сообщения. Помните, что вы отвечаете на вопрос читателей в будущем, и эти люди могут не знать причин, по которым вы предлагаете код.
Ferrybig
0
Java 7 и более поздние версии:
import sun.misc.IOUtils;...InputStream in =...;byte[] buf =IOUtils.readFully(in,-1,false);
sun.misc.IOUtilsэто не «Java 7». Это собственный, специфичный для реализации класс, который может отсутствовать в других реализациях JRE и может исчезнуть без предупреждения в одном из следующих выпусков.
Решение в Kotlin (конечно, будет работать и на Java), которое включает оба случая, когда вы знаете размер или нет:
fun InputStream.readBytesWithSize(size:Long):ByteArray?{return when {
size <0L->this.readBytes()
size ==0L->ByteArray(0)
size >Int.MAX_VALUE ->nullelse->{
val sizeInt = size.toInt()
val result =ByteArray(sizeInt)
readBytesIntoByteArray(result, sizeInt)
result
}}}
fun InputStream.readBytesIntoByteArray(byteArray:ByteArray,bytesToRead:Int=byteArray.size){
var offset =0while(true){
val read =this.read(byteArray, offset, bytesToRead - offset)if(read ==-1)break
offset += read
if(offset >= bytesToRead)break}}
Если вы знаете размер, это сэкономит вам вдвое больше используемой памяти по сравнению с другими решениями (в скором времени, но все же может оказаться полезным). Это потому, что вы должны прочитать весь поток до конца, а затем преобразовать его в байтовый массив (аналог ArrayList, который вы конвертируете в массив).
Так, если вы работаете на Android, например, и у вас есть какой-то Uri для обработки, вы можете попытаться получить размер, используя это:
fun getStreamLengthFromUri(context:Context, uri:Uri):Long{
context.contentResolver.query(uri, arrayOf(MediaStore.MediaColumns.SIZE),null,null,null)?.use {if(!it.moveToNext())return@use
val fileSize = it.getLong(it.getColumnIndex(MediaStore.MediaColumns.SIZE))if(fileSize >0)return fileSize
}//if you wish, you can also get the file-path from the uri here, and then try to get its size, using this: https://stackoverflow.com/a/61835665/878126FileUtilEx.getFilePathFromUri(context, uri,false)?.use {
val file = it.file
val fileSize = file.length()if(fileSize >0)return fileSize
}
context.contentResolver.openInputStream(uri)?.use { inputStream ->if(inputStream is FileInputStream)return inputStream.channel.size()else{
var bytesCount =0Lwhile(true){
val available = inputStream.available()if(available ==0)break
val skip = inputStream.skip(available.toLong())if(skip <0)break
bytesCount += skip
}if(bytesCount >0L)return bytesCount
}}return-1L}
/*InputStream class_InputStream = null;
I am reading class from DB
class_InputStream = rs.getBinaryStream(1);
Your Input stream could be from any source
*/int thisLine;ByteArrayOutputStream bos =newByteArrayOutputStream();while((thisLine = class_InputStream.read())!=-1){
bos.write(thisLine);}
bos.flush();byte[] yourBytes = bos.toByteArray();/*Don't forget in the finally block to close ByteArrayOutputStream & InputStream
In my case the IS is from resultset so just closing the rs will do it*/if(bos !=null){
bos.close();}
Закрытие и сброс босов - пустая трата щелчков клавиатуры. Закрытие входного потока, скорее всего, поможет. Чтение одного байта за раз неэффективно. Смотрите ответ Нуман.
Ответы:
Вы можете использовать Apache Commons IO для решения этой и подобных задач.
IOUtils
Тип имеет статический метод , чтобы прочитатьInputStream
и возвращалbyte[]
.Внутренне это создает
ByteArrayOutputStream
и копирует байты в вывод, а затем вызываетtoByteArray()
. Он обрабатывает большие файлы, копируя байты в блоки по 4 КБ.источник
FastArrayList
или их мягкие и слабые справочные карты, и вернуться и рассказать мне, насколько «хорошо проверена» эта библиотека. Это куча мусораInputStream is;
byte[] filedata=ByteStreams.toByteArray(is);
Вам нужно прочитать каждый байт из вашего
InputStream
и записать его вByteArrayOutputStream
.Затем вы можете получить базовый байтовый массив, вызвав
toByteArray()
:источник
Наконец, через двадцать лет, благодаря Java 9 , существует простое решение без необходимости использования сторонней библиотеки :
Обратите внимание также на удобные методы
readNBytes(byte[] b, int off, int len)
иtransferTo(OutputStream)
решение повторяющихся потребностей.источник
Используйте ванильный Java
DataInputStream
и егоreadFully
метод (существует по крайней мере с Java 1.4):У этого метода есть и другие варианты, но я все время использую его для этого варианта использования.
источник
DataInputStream
используется в основном для чтения первичных типов (Longs, Shorts, Chars ...) из потока, поэтому мы можем рассматривать это использование как неправильное использование класса.InputStream.read
.Если вы используете Google Guava , это будет так просто, как:
источник
ByteStreams
комментируется@Beta
Как всегда, в Spring Framework (spring-core начиная с 3.2.2) есть что-то для вас:
StreamUtils.copyToByteArray()
источник
источник
Безопасное решение (с возможностью
close
потокового воспроизведения):Версия Java 9+:
Версия Java 8:
Версия Kotlin (когда Java 9+ недоступна):
Чтобы избежать вложенности
use
смотрите здесь .источник
Вам действительно нужно изображение как
byte[]
? Что именно вы ожидаете вbyte[]
- полного содержимого файла изображения, закодированного в любом формате, в котором находится файл изображения, или значений пикселей RGB?Другие ответы здесь показывают, как прочитать файл в
byte[]
. Вашbyte[]
файл будет содержать точное содержимое файла, и вам потребуется его расшифровать, чтобы что-нибудь сделать с данными изображения.Стандартный API Java для чтения (и записи) изображений - это API ImageIO, который вы можете найти в пакете
javax.imageio
. Вы можете прочитать изображение из файла с помощью одной строки кода:Это даст вам, а
BufferedImage
неbyte[]
. Чтобы получить данные изображения, вы можете позвонитьgetRaster()
наBufferedImage
. Это даст вамRaster
объект, который имеет методы доступа к данным пикселя (она имеет несколькоgetPixel()
/getPixels()
методов).Lookup документацию API для
javax.imageio.ImageIO
,java.awt.image.BufferedImage
, иjava.awt.image.Raster
т.д.ImageIO по умолчанию поддерживает несколько форматов изображений: JPEG, PNG, BMP, WBMP и GIF. Можно добавить поддержку большего количества форматов (вам понадобится плагин, который реализует интерфейс поставщика услуг ImageIO).
Смотрите также следующий учебник: Работа с изображениями
источник
В случае, если кто-то все еще ищет решение без зависимости и если у вас есть файл .
источник
Если вы не хотите использовать библиотеку Apache commons-io, этот фрагмент взят из класса sun.misc.IOUtils. Это почти в два раза быстрее, чем обычная реализация, использующая ByteBuffers:
источник
источник
@ Adamski: Вы можете полностью избежать буфера.
Код скопирован с http://www.exampledepot.com/egs/java.io/File2ByteArray.html (Да, он очень многословный, но требует половины объема памяти, как и другое решение.)
источник
is.close()
еслиoffset < bytes.length
илиInputStream
не будет закрыто, если выдается это исключение.источник
InputStream
вBufferedInputStream
коде до этого уменьшит количество вызовов ОС и значительно уменьшит недостатки производительности, этот код все равно будет выполнять ненужное ручное копирование из одного буфера в другой.Java 9 даст вам, наконец, хороший метод:
источник
InputStram.readAllBytes()
одним?Я знаю, что уже слишком поздно, но я думаю, что это более чистое решение, которое более читабельно ...
источник
Java 8 way (спасибо BufferedReader и Adam Bien )
Обратите внимание, что это решение стирает возврат каретки ('\ r') и может быть неуместным.
источник
String
. ОП проситbyte[]
.\r
проблема. Этот метод преобразует байты в символы и обратно (используя набор символов по умолчанию для InputStreamReader). Любые байты, которые недопустимы в кодировке символов по умолчанию (скажем, -1 для UTF-8 в Linux), будут повреждены, что может даже изменить количество байтов.Я попытался отредактировать ответ @ numan с исправлением для записи мусорных данных, но редактирование было отклонено. Хотя этот короткий кусок кода не является чем-то блестящим, я не вижу другого лучшего ответа. Вот что имеет для меня наибольшее значение:
Кстати, ByteArrayOutputStream не нужно закрывать. конструкции try / finally опущены для удобства чтения
источник
Смотрите
InputStream.available()
документацию:источник
Оберните его в DataInputStream, если он по какой-то причине не находится на столе, просто используйте read, чтобы забить его, пока он не даст вам -1 или весь запрашиваемый блок.
источник
Мы наблюдаем некоторую задержку для нескольких транзакций AWS при преобразовании объекта S3 в ByteArray.
Примечание. Объект S3 - это документ PDF (максимальный размер - 3 МБ).
Мы используем параметр # 1 (org.apache.commons.io.IOUtils) для преобразования объекта S3 в ByteArray. Мы заметили, что S3 предоставляет встроенный метод IOUtils для преобразования объекта S3 в ByteArray, мы просим вас подтвердить наилучший способ преобразования объекта S3 в ByteArray, чтобы избежать задержки.
Опция 1:
Вариант № 2:
Также дайте мне знать, если у нас есть какой-либо другой лучший способ преобразовать объект s3 в bytearray
источник
Другой случай получить правильный байтовый массив через поток после отправки запроса на сервер и ожидания ответа.
источник
Вы делаете дополнительную копию, если используете ByteArrayOutputStream. Если вы знаете длину потока до того, как начнете его читать (например, InputStream на самом деле является FileInputStream, и вы можете вызвать file.length () для файла, или InputStream является записью в файле zipfile InputStream, и вы можете вызвать zipEntry. length ()), тогда гораздо лучше записать непосредственно в массив byte [] - он использует половину памяти и экономит время.
Обратите внимание, что последняя строка выше относится к файлам, усеченным во время чтения потока, если вам нужно обработать эту возможность, но если файл становится длиннее во время чтения потока, содержимое массива byte [] не будет удлиняться чтобы включить новое содержимое файла, массив будет просто урезан до старой длины inputStreamLength .
источник
Я использую это.
источник
Это моя версия для копирования и вставки:
источник
Java 7 и более поздние версии:
источник
sun.misc.IOUtils
это не «Java 7». Это собственный, специфичный для реализации класс, который может отсутствовать в других реализациях JRE и может исчезнуть без предупреждения в одном из следующих выпусков.Вы можете попробовать Cactoos :
источник
Вот оптимизированная версия, которая старается максимально избежать копирования байтов данных:
источник
Решение в Kotlin (конечно, будет работать и на Java), которое включает оба случая, когда вы знаете размер или нет:
Если вы знаете размер, это сэкономит вам вдвое больше используемой памяти по сравнению с другими решениями (в скором времени, но все же может оказаться полезным). Это потому, что вы должны прочитать весь поток до конца, а затем преобразовать его в байтовый массив (аналог ArrayList, который вы конвертируете в массив).
Так, если вы работаете на Android, например, и у вас есть какой-то Uri для обработки, вы можете попытаться получить размер, используя это:
источник
источник