Internamente, esto crea ay ByteArrayOutputStreamcopia los bytes a la salida, luego llama toByteArray(). Maneja archivos grandes copiando los bytes en bloques de 4KiB.
Por la falta de escribir 4 líneas de código, ¿cree que vale la pena importar una dependencia de terceros?
oxbow_lakes
217
Si hay una biblioteca que maneja el requisito, y se ocupa del procesamiento de archivos grandes, y está bien probado, seguramente la pregunta es ¿por qué lo escribiría yo mismo? El frasco es solamente 107KB y si tiene la necesidad de un método de ello, es probable que el uso de otros también
Rich Vendedor
242
@oxbow_lakes: Teniendo en cuenta la asombrosa cantidad de malas implementaciones de esta función que he visto en mi vida desarrollador, creo que sí es muy mucho la pena la dependencia externa para hacerlo bien.
Joachim Sauer
17
¿Por qué no ir y echar un vistazo a las cosas comunes de Apache como FastArrayListo sus mapas de referencia blandos y débiles y volver a decirme cuán "bien probada" es esta biblioteca? Es un montón de basura
oxbow_lakes
87
Además de Apache commons-io, echa un vistazo a la clase ByteStreams de Google Guava . InputStream is;byte[] filedata=ByteStreams.toByteArray(is);
michaelok
446
Debe leer cada byte de su InputStreamy escribirlo en unByteArrayOutputStream .
Luego puede recuperar la matriz de bytes subyacente llamando a 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();
¿Qué pasa con el tamaño del byte recién creado []. ¿Por qué es 16384? ¿Cómo podría determinar el tamaño exacto correcto? Muchas gracias.
Ondrej Bozek
66
16384 es una elección bastante arbitraria, aunque tiendo a favorecer potencias de 2 para aumentar la posibilidad de que la matriz se alinee con los límites de las palabras. La respuesta de pihentagy muestra cómo puede evitar usar un búfer intermedio, sino más bien asignar una matriz del tamaño correcto. A menos que esté tratando con archivos grandes, personalmente prefiero el código anterior, que es más elegante y se puede usar para InputStreams, donde no se conoce de antemano el número de bytes a leer.
Adamski el
@Adamski ¿No es la creación de una matriz de bytes mucho más grande de lo que esperas que los datos estén en la secuencia, desperdicia la memoria?
Paul Brewczynski
@bluesm: Sí, eso es correcto. Sin embargo, en mi ejemplo, la matriz de bytes tiene solo 16 Kb y es muy pequeña para los estándares actuales. Además, por supuesto, esta memoria se liberará nuevamente después.
Adamski el
55
@Adamski Una gran cantidad de hardware de infraestructura, servidores web y componentes de la capa del sistema operativo están utilizando buffers 4K para mover datos, por lo que esa es la razón del número exacto, pero el punto principal es que obtienes tan poco aumento de rendimiento al pasar 4K que generalmente se considera un desperdicio de memoria. Supongo que esto sigue siendo cierto, ¡porque tengo un conocimiento de hace una década!
312
Finalmente, después de veinte años, hay una solución simple sin la necesidad de una biblioteca de terceros, gracias a Java 9 :
+1 para usar las bibliotecas estándar en lugar de una dependencia de terceros. Desafortunadamente no me funciona porque no sé la longitud de la transmisión por adelantado.
Andrew Spencer
2
¿Qué es imgFile? No puede ser un InputStream, que se suponía que era la entrada de este método
Janus Troelsen
44
@janus es un "Archivo". de esta manera solo funciona si conoce la longitud del archivo o el recuento de bytes para leer.
dermoritz
55
Lo interesante, pero debe saber la longitud exacta de la (parte de) la secuencia para leer. Además, la clase DataInputStreamse usa principalmente para leer tipos primarios (Longs, Shorts, Chars ...) de una secuencia, por lo que podemos ver este uso como un mal uso de la clase.
Olivier Faucheux
17
Si ya conoce la longitud de los datos para leer de la secuencia, esto no es mejor que InputStream.read.
Como la mayoría de los demás, quería evitar usar una biblioteca de terceros para algo tan simple, pero Java 9 no es una opción en este momento ... afortunadamente, ya estaba usando Spring.
scottysseus
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();}
Es un ejemplo y, como tal, la brevedad está a la orden del día. También devolver nulo aquí sería la elección adecuada en algunos casos (aunque en un entorno de producción también tendría un manejo y documentación de excepción adecuados).
11
Entiendo la brevedad en un ejemplo, pero ¿por qué no hacer que el método de ejemplo arroje IOException en lugar de tragarlo y devolver un valor sin sentido?
pendor
44
Me he tomado la libertad de cambiar de 'return null' a 'throw IOException'
kritzikratzi
3
Probar con recursos no es necesario aquí, porque ByteArrayOutputStream # close () no hace nada. (ByteArrayOutputStream # flush () no es necesario y tampoco hace nada.)
Versión de Kotlin (cuando Java 9+ no es accesible):
@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()}}
¿No significa que en algún momento tendrías el doble de memoria utilizada, porque tienes tanto el búfer como la matriz de bytes? ¿No hay una manera de enviar los bytes directamente a la matriz de bytes de salida?
Desarrollador de Android
@desarrollador de Android; Lo siento. No se la respuesta! Pero no lo creo. Creo que de esta manera (usando buffer) es una forma optimizada.
Mir-Ismaili
Lo he comprobado y lo hace, pero parece que es la única solución que puede elegir cuando no conoce el tamaño. Si ya conoce el tamaño, puede crear directamente la matriz de bytes con el tamaño dado y llenarlo. Por lo tanto, utiliza una función que obtendrá un parámetro del tamaño del byte, y si es válido, úselo para crear y llenar directamente la matriz de bytes, sin crear ningún otro objeto grande.
Desarrollador de Android
@desarrollador de Android; Gracias por tu información. Yo no los conocía.
Mir-Ismaili
19
¿Realmente necesitas la imagen como a byte[]? ¿Qué esperas exactamente en elbyte[] contenido completo de un archivo de imagen, codificado en cualquier formato en el que esté el archivo de imagen, o valores de píxeles RGB?
Otras respuestas aquí le muestran cómo leer un archivo en un byte[]. Su byte[]contendrá el contenido exacto del archivo, y que había necesidad de decodificación que hacer nada con los datos de imagen.
La API estándar de Java para leer (y escribir) imágenes es la API ImageIO, que puede encontrar en el paquete javax.imageio. Puede leer una imagen de un archivo con una sola línea de código:
Esto te dará un BufferedImage, no un byte[]. Para obtener los datos de la imagen, puede llamar getRaster()al BufferedImage. Esto le dará un Rasterobjeto, que tiene métodos para acceder a los datos de píxeles (tiene varios getPixel()/getPixels() métodos).
Buscar la documentación de la API para javax.imageio.ImageIO, java.awt.image.BufferedImage, java.awt.image.Rasteretc.
ImageIO admite varios formatos de imagen de forma predeterminada: JPEG, PNG, BMP, WBMP y GIF. Es posible agregar soporte para más formatos (necesitaría un complemento que implemente la interfaz del proveedor de servicios ImageIO).
Digamos, ¿qué pasa si la matriz de bytes es demasiado grande, lo que podría causar OOM para el montón? ¿Existe una solución similar que usará JNI para almacenar los bytes, y luego podríamos usar inputStream de los datos almacenados allí (una especie de caché temporal)?
Desarrollador de Android
14
Si no desea usar la biblioteca Apache commons-io, este fragmento se toma de la clase sun.misc.IOUtils. Es casi el doble de rápido que la implementación común con ByteBuffers:
Esta es una solución un poco extraña, la longitud es un límite superior en la longitud de la matriz. Si conoce la longitud, todo lo que necesita es: byte [] salida = nuevo byte [longitud]; is.read (salida); (pero vea mi respuesta)
Luke Hutchison
@ luke-hutchison como dije, esta es la solución de sun.misc.IOUtils. En los casos más comunes, no conoce el tamaño de un InputStream por adelantado, entonces si (length == -1) length = Integer.MAX_VALUE; aplica. Esta solución funciona, incluso si la longitud dada es mayor que la longitud de InputStream.
Kristian Kraljic
@LukeHutchison Si conoce la longitud, puede manejarlo con unas pocas líneas. Si observa cada respuesta, todos se quejan de que no se conoce la longitud. Finalmente, una respuesta que es estándar, se puede usar con Java 7 Android y no requiere ninguna biblioteca externa.
Csaba Toth
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;}
Por supuesto, pero deberían saber el tamaño: "Quiero leer una imagen"
piratería
1
Si conoce el tamaño, Java le proporcionará el código. vea mi respuesta o google para "DataInputStream" y es el método readFully.
dermoritz
Debe agregar is.close()si offset < bytes.lengtho InputStreamno se cerrará si se produce esa excepción.
Jared Rummler
3
Entonces mejor, deberías usar try-with-resources
pihentagy
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();
Sin embargo, por lo general, el sistema operativo ya es suficiente para que esto no sea una gran preocupación para los archivos más pequeños. No es como si el cabezal del disco duro leyera cada byte por separado (un disco duro es una placa de vidrio giratoria con información codificada magnética, un poco como ese icono extraño que usamos para guardar datos: P).
Maarten Bodewes
66
@Maarten Bodewes: la mayoría de los dispositivos tienen una especie de transferencia de bloque, por lo que no todas las lecturas () causarán un acceso real al dispositivo, pero tener una llamada al sistema operativo por byte ya es suficiente para matar el rendimiento. Si bien envolviendo la InputStreamde una BufferedInputStreamantes de que el código se reduciría el OS-llamadas y mitigar los inconvenientes de rendimiento significativamente, que el código todavía va a hacer el trabajo manual de la copia innecesaria de un tampón a otro.
¿Cuál es la diferencia entre esto y InputStram.readAllBytes()eso es de una sola línea?
Slava Semushin
2
Sé que es demasiado tarde, pero aquí creo que es una solución más limpia que es más legible ...
/**
* 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();}
No solo \reso podría ser un problema. Este método convierte los bytes en caracteres y viceversa (usando el juego de caracteres predeterminado para InputStreamReader). Todos los bytes que no sean válidos en la codificación de caracteres predeterminada (por ejemplo, -1 para UTF-8 en Linux) se dañarán, lo que podría incluso cambiar el número de bytes.
seanf
Parece que esta es una buena respuesta, pero orientada al texto. El comprador tenga cuidado.
Wheezil
1
Intenté editar la respuesta de @ numan con una solución para escribir datos basura, pero la edición fue rechazada. Si bien este breve fragmento de código no es nada brillante, no puedo ver ninguna otra respuesta mejor. Esto es lo que tiene más sentido para mí:
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();
Por cierto, ByteArrayOutputStream no necesita cerrarse. try / finalmente construcciones omitidas por legibilidad
Es particularmente importante darse cuenta de que no debe usar este método para dimensionar un contenedor y asumir que puede leer la totalidad de la secuencia sin necesidad de cambiar el tamaño del contenedor. Esas personas que llaman probablemente deberían escribir todo lo que leen en un ByteArrayOutputStream y convertirlo en una matriz de bytes. Alternativamente, si está leyendo desde un archivo, File.length devuelve la longitud actual del archivo (aunque suponiendo que la longitud del archivo no puede cambiar puede ser incorrecto, la lectura de un archivo es inherentemente picante).
Envuélvalo en un DataInputStream si eso está fuera de la tabla por alguna razón, solo use leer para martillarlo hasta que le dé un -1 o el bloque completo que solicitó.
Estamos viendo algunos retrasos en algunas transacciones de AWS, al convertir el objeto S3 en ByteArray.
Nota: El objeto S3 es un documento PDF (el tamaño máximo es de 3 mb).
Estamos utilizando la opción # 1 (org.apache.commons.io.IOUtils) para convertir el objeto S3 a ByteArray. Hemos notado que S3 proporciona el método IOUtils incorporado para convertir el objeto S3 a ByteArray, se le solicita que confirme cuál es la mejor manera de convertir el objeto S3 a ByteArray para evitar el retraso.
Opción 1:
import org.apache.commons.io.IOUtils;
is = s3object.getObjectContent();
content =IOUtils.toByteArray(is);
Opcion 2:
import com.amazonaws.util.IOUtils;
is = s3object.getObjectContent();
content =IOUtils.toByteArray(is);
También avíseme si tenemos otra forma mejor de convertir el objeto s3 a bytearray
El otro caso es obtener la matriz de bytes correcta a través de la secuencia, después de enviar la solicitud al servidor y esperar la respuesta.
/**
* 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);
Estás haciendo una copia adicional si usas ByteArrayOutputStream. Si conoce la longitud de la secuencia antes de comenzar a leerla (por ejemplo, InputStream es en realidad un FileInputStream, y puede llamar a file.length () en el archivo, o InputStream es una entrada de archivo zip InputStream, y puede llamar a zipEntry. length ()), entonces es mucho mejor escribir directamente en la matriz de bytes []: usa la mitad de la memoria y ahorra tiempo.
// 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);
Nota: la última línea anterior trata con archivos que se truncan mientras se lee la secuencia, si necesita manejar esa posibilidad, pero si el archivo se alarga mientras se lee la secuencia, los contenidos en la matriz byte [] no se alargarán para incluir el nuevo contenido del archivo, la matriz simplemente se truncará a la longitud antigua inputStreamLength .
Agregue alguna explicación con la respuesta de cómo esta respuesta ayuda a OP a solucionar el problema actual
ρяσѕρєя K
0
Esta es mi versión de copiar y pegar:
@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();}
Si bien este fragmento de código puede resolver la pregunta, incluir una explicación realmente ayuda a mejorar la calidad de su publicación. Recuerde que está respondiendo la pregunta para los lectores en el futuro, y que esas personas podrían no conocer los motivos de su sugerencia de código.
Ferrybig
0
Java 7 y posterior:
import sun.misc.IOUtils;...InputStream in =...;byte[] buf =IOUtils.readFully(in,-1,false);
sun.misc.IOUtilsno es "Java 7". Es una clase patentada de implementación específica que puede no estar presente en otras implementaciones de JRE y puede desaparecer sin previo aviso en una de las próximas versiones.
Solución en Kotlin (también funcionará en Java, por supuesto), que incluye ambos casos de cuándo conoce el tamaño o no:
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}}
Si conoce el tamaño, le ahorra tener el doble de memoria utilizada en comparación con las otras soluciones (en un breve momento, pero aún podría ser útil). Esto se debe a que tiene que leer todo el flujo hasta el final y luego convertirlo en una matriz de bytes (similar a ArrayList que convierte en solo una matriz).
Entonces, si está en Android, por ejemplo, y tiene que manejar algunos Uri, puede intentar obtener el tamaño usando esto:
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();}
Cerrar y enjuagar bos es un desperdicio de clics del teclado. Cerrar el flujo de entrada es más probable que ayude. Leer un byte a la vez es ineficiente. Ver la respuesta de Numan.
Respuestas:
Puede usar Apache Commons IO para manejar esta y otras tareas similares.
El
IOUtils
tipo tiene un método estático para leerInputStream
y devolver abyte[]
.Internamente, esto crea ay
ByteArrayOutputStream
copia los bytes a la salida, luego llamatoByteArray()
. Maneja archivos grandes copiando los bytes en bloques de 4KiB.fuente
FastArrayList
o sus mapas de referencia blandos y débiles y volver a decirme cuán "bien probada" es esta biblioteca? Es un montón de basuraInputStream is;
byte[] filedata=ByteStreams.toByteArray(is);
Debe leer cada byte de su
InputStream
y escribirlo en unByteArrayOutputStream
.Luego puede recuperar la matriz de bytes subyacente llamando a
toByteArray()
:fuente
Finalmente, después de veinte años, hay una solución simple sin la necesidad de una biblioteca de terceros, gracias a Java 9 :
Tenga en cuenta también los métodos de conveniencia
readNBytes(byte[] b, int off, int len)
ytransferTo(OutputStream)
abordar las necesidades recurrentes.fuente
Utilice Java de Vanilla
DataInputStream
y sureadFully
método (existe desde al menos Java 1.4):Hay algunos otros sabores de este método, pero lo uso todo el tiempo para este caso de uso.
fuente
DataInputStream
se usa principalmente para leer tipos primarios (Longs, Shorts, Chars ...) de una secuencia, por lo que podemos ver este uso como un mal uso de la clase.InputStream.read
.Si usa google guava , será tan simple como:
fuente
ByteStreams
está anotado con@Beta
Como siempre, Spring Framework (spring-core desde 3.2.2) tiene algo para usted:
StreamUtils.copyToByteArray()
fuente
fuente
Solución segura (con capacidad de
close
transmisión correcta):Versión de Java 9+:
Versión de Java 8:
Versión de Kotlin (cuando Java 9+ no es accesible):
Para evitar anidados
use
ver aquí .fuente
¿Realmente necesitas la imagen como a
byte[]
? ¿Qué esperas exactamente en elbyte[]
contenido completo de un archivo de imagen, codificado en cualquier formato en el que esté el archivo de imagen, o valores de píxeles RGB?Otras respuestas aquí le muestran cómo leer un archivo en un
byte[]
. Subyte[]
contendrá el contenido exacto del archivo, y que había necesidad de decodificación que hacer nada con los datos de imagen.La API estándar de Java para leer (y escribir) imágenes es la API ImageIO, que puede encontrar en el paquete
javax.imageio
. Puede leer una imagen de un archivo con una sola línea de código:Esto te dará un
BufferedImage
, no unbyte[]
. Para obtener los datos de la imagen, puede llamargetRaster()
alBufferedImage
. Esto le dará unRaster
objeto, que tiene métodos para acceder a los datos de píxeles (tiene variosgetPixel()
/getPixels()
métodos).Buscar la documentación de la API para
javax.imageio.ImageIO
,java.awt.image.BufferedImage
,java.awt.image.Raster
etc.ImageIO admite varios formatos de imagen de forma predeterminada: JPEG, PNG, BMP, WBMP y GIF. Es posible agregar soporte para más formatos (necesitaría un complemento que implemente la interfaz del proveedor de servicios ImageIO).
Consulte también el siguiente tutorial: Trabajar con imágenes
fuente
En caso de que alguien todavía esté buscando una solución sin dependencia y si tiene un archivo .
fuente
Si no desea usar la biblioteca Apache commons-io, este fragmento se toma de la clase sun.misc.IOUtils. Es casi el doble de rápido que la implementación común con ByteBuffers:
fuente
fuente
@ Adamski: puede evitar el búfer por completo.
Código copiado de http://www.exampledepot.com/egs/java.io/File2ByteArray.html (Sí, es muy detallado, pero necesita la mitad del tamaño de la memoria que la otra solución).
fuente
is.close()
sioffset < bytes.length
oInputStream
no se cerrará si se produce esa excepción.fuente
InputStream
de unaBufferedInputStream
antes de que el código se reduciría el OS-llamadas y mitigar los inconvenientes de rendimiento significativamente, que el código todavía va a hacer el trabajo manual de la copia innecesaria de un tampón a otro.Java 9 finalmente te dará un buen método:
fuente
InputStram.readAllBytes()
eso es de una sola línea?Sé que es demasiado tarde, pero aquí creo que es una solución más limpia que es más legible ...
fuente
Java 8 way (gracias a BufferedReader y Adam Bien )
Tenga en cuenta que esta solución elimina el retorno de carro ('\ r') y puede ser inapropiado.
fuente
String
. OP está pidiendobyte[]
.\r
eso podría ser un problema. Este método convierte los bytes en caracteres y viceversa (usando el juego de caracteres predeterminado para InputStreamReader). Todos los bytes que no sean válidos en la codificación de caracteres predeterminada (por ejemplo, -1 para UTF-8 en Linux) se dañarán, lo que podría incluso cambiar el número de bytes.Intenté editar la respuesta de @ numan con una solución para escribir datos basura, pero la edición fue rechazada. Si bien este breve fragmento de código no es nada brillante, no puedo ver ninguna otra respuesta mejor. Esto es lo que tiene más sentido para mí:
Por cierto, ByteArrayOutputStream no necesita cerrarse. try / finalmente construcciones omitidas por legibilidad
fuente
Ver la
InputStream.available()
documentación:fuente
Envuélvalo en un DataInputStream si eso está fuera de la tabla por alguna razón, solo use leer para martillarlo hasta que le dé un -1 o el bloque completo que solicitó.
fuente
Estamos viendo algunos retrasos en algunas transacciones de AWS, al convertir el objeto S3 en ByteArray.
Nota: El objeto S3 es un documento PDF (el tamaño máximo es de 3 mb).
Estamos utilizando la opción # 1 (org.apache.commons.io.IOUtils) para convertir el objeto S3 a ByteArray. Hemos notado que S3 proporciona el método IOUtils incorporado para convertir el objeto S3 a ByteArray, se le solicita que confirme cuál es la mejor manera de convertir el objeto S3 a ByteArray para evitar el retraso.
Opción 1:
Opcion 2:
También avíseme si tenemos otra forma mejor de convertir el objeto s3 a bytearray
fuente
El otro caso es obtener la matriz de bytes correcta a través de la secuencia, después de enviar la solicitud al servidor y esperar la respuesta.
fuente
Estás haciendo una copia adicional si usas ByteArrayOutputStream. Si conoce la longitud de la secuencia antes de comenzar a leerla (por ejemplo, InputStream es en realidad un FileInputStream, y puede llamar a file.length () en el archivo, o InputStream es una entrada de archivo zip InputStream, y puede llamar a zipEntry. length ()), entonces es mucho mejor escribir directamente en la matriz de bytes []: usa la mitad de la memoria y ahorra tiempo.
Nota: la última línea anterior trata con archivos que se truncan mientras se lee la secuencia, si necesita manejar esa posibilidad, pero si el archivo se alarga mientras se lee la secuencia, los contenidos en la matriz byte [] no se alargarán para incluir el nuevo contenido del archivo, la matriz simplemente se truncará a la longitud antigua inputStreamLength .
fuente
Yo uso esto.
fuente
Esta es mi versión de copiar y pegar:
fuente
Java 7 y posterior:
fuente
sun.misc.IOUtils
no es "Java 7". Es una clase patentada de implementación específica que puede no estar presente en otras implementaciones de JRE y puede desaparecer sin previo aviso en una de las próximas versiones.Puedes probar Cactoos :
fuente
Aquí hay una versión optimizada, que intenta evitar copiar bytes de datos tanto como sea posible:
fuente
Solución en Kotlin (también funcionará en Java, por supuesto), que incluye ambos casos de cuándo conoce el tamaño o no:
Si conoce el tamaño, le ahorra tener el doble de memoria utilizada en comparación con las otras soluciones (en un breve momento, pero aún podría ser útil). Esto se debe a que tiene que leer todo el flujo hasta el final y luego convertirlo en una matriz de bytes (similar a ArrayList que convierte en solo una matriz).
Entonces, si está en Android, por ejemplo, y tiene que manejar algunos Uri, puede intentar obtener el tamaño usando esto:
fuente
fuente