Internamente, isso cria ae ByteArrayOutputStreamcopia os bytes para a saída e depois chama toByteArray(). Ele lida com arquivos grandes, copiando os bytes em blocos de 4KiB.
Por falta de escrever 4 linhas de código, você acha que vale a pena importar uma dependência de terceiros?
Oxbow_lakes 12/08/09
217
Se existe uma biblioteca que lida com o requisito, lida com o processamento de arquivos grandes e é bem testada, certamente a pergunta é por que eu mesmo a escreveria? O jar tem apenas 107 KB e, se você precisar de um método, provavelmente usará outros também.
Rich Seller
242
@oxbow_lakes: considerando a quantidade impressionante de errado implementações deste recurso que já vi em minha vida desenvolvedor, eu sinto que sim , é muito muito valor a dependência externa de acertar.
Joachim Sauer
17
Por que não dar uma olhada no Apache commons, como em FastArrayListseus mapas de referência suaves e fracos, e voltar para me dizer como esta biblioteca é "bem testada". É uma pilha de lixo
oxbow_lakes
87
Além do Apache commons-io, confira a classe ByteStreams no Google Guava . InputStream is;byte[] filedata=ByteStreams.toByteArray(is);
michaelok
446
Você precisa ler cada byte do seu InputStreame gravá-lo em a ByteArrayOutputStream.
Você pode recuperar a matriz de bytes subjacente chamando 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();
E o tamanho do byte recém-criado []. Por que é 16384? Como posso determinar o tamanho exato exato? Muito obrigado.
Ondrej Bozek
6
16384 é uma escolha bastante arbitrária, embora eu tenha tendência a favorecer potências de 2 para aumentar a chance da matriz se alinhar com os limites das palavras. A resposta da pihentagy mostra como você pode evitar o uso de um buffer intermediário, mas alocar uma matriz do tamanho correto. A menos que você esteja lidando com arquivos grandes, eu pessoalmente prefiro o código acima, que é mais elegante e pode ser usado para InputStreams em que o número de bytes a serem lidos não é conhecido antecipadamente.
Adamski
@Adamski A criação de uma matriz de bytes não é muito maior do que você espera que os dados estejam no fluxo, desperdiça a memória?
Paul Brewczynski
@ bluesm: Sim, está correto. No entanto, no meu exemplo, a matriz de bytes é de apenas 16 KB e é minúscula para os padrões atuais. Além disso, é claro que essa memória será liberada novamente posteriormente.
Adamski
5
@Adamski Um monte de hardware de infraestrutura, servidores da web e componentes da camada do sistema operacional estão usando buffers de 4K para mover dados, então esse é o motivo do número exato, mas o ponto principal é que você obtém tão pouco aumento de desempenho ao passar por 4K que geralmente é considerado um desperdício de memória. Eu estou supondo que isso ainda é verdade, porque é o conhecimento que tenho há uma década!
312
Finalmente, depois de vinte anos, há uma solução simples sem a necessidade de uma biblioteca de terceiros, graças ao Java 9 :
+1 por usar as bibliotecas padrão em vez de uma dependência de terceiros. Infelizmente, isso não funciona para mim porque não sei a duração do fluxo antecipadamente.
Andrew Spencer
2
o que é imgFile? Não pode ser um InputStream, que deveria ser a entrada desse método
Janus Troelsen
4
@janus é um "arquivo". dessa forma, só funciona se você souber o comprimento do arquivo ou a contagem de bytes a serem lidos.
Dermoritz
5
Interessante, mas você deve saber o comprimento exato do (parte do) fluxo para ler. Além disso, a classe DataInputStreamé usada principalmente para ler tipos primários (Longs, Shorts, Chars ...) de um fluxo, para que possamos ver esse uso como um uso indevido da classe.
Olivier Faucheux
17
Se você já sabe o tamanho dos dados a serem lidos do fluxo, isso não é melhor que InputStream.read.
Como a maioria dos outros, eu queria evitar o uso de uma biblioteca de terceiros para algo tão simples, mas o Java 9 não é uma opção no momento ... felizmente, eu já estava usando o 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();}
É um exemplo e, como tal, a brevidade está na ordem do dia. Também retornar nulo aqui seria a escolha adequada em alguns casos (embora em um ambiente de produção você também tenha manipulação e documentação de exceção).
11
Entendo a brevidade em um exemplo, mas por que não fazer o método de exemplo lançar IOException em vez de engoli-lo e retornar um valor sem sentido?
Pendor
4
Tomei a liberdade de mudar de 'null retorno' para 'jogar IOException'
kritzikratzi
3
A tentativa com recursos não é necessária aqui, porque ByteArrayOutputStream # close () não faz nada. (ByteArrayOutputStream # flush () não é necessário e também não faz nada.)
Versão Kotlin (quando o Java 9+ não está acessível):
@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()}}
Isso não significa que, em algum momento, você teria o dobro da memória usada, porque possui o buffer e a matriz de bytes? Não existe uma maneira de enviar os bytes diretamente para a matriz de bytes de saída?
desenvolvedor android
@androiddeveloper; Eu sinto Muito. Eu não sei a resposta! Mas acho que não. Eu acho que desta maneira (usando buffer) é uma maneira otimizada.
Mir-Ismaili
Eu verifiquei e sim, mas parece que é a única solução que você pode escolher quando não sabe o tamanho. Se você já conhece o tamanho, pode criar diretamente a matriz de bytes com o tamanho especificado e preenchê-lo. Portanto, você usa uma função que obterá um parâmetro do tamanho de bytes e, se for válido, use-a para criar e preencher diretamente a matriz de bytes, sem criar nenhum outro objeto grande.
desenvolvedor android
@androiddeveloper; Obrigado pela sua informação. Eu não os conhecia.
Mir-Ismaili
19
Você realmente precisa da imagem como um byte[]? O que exatamente você espera nobyte[] - o conteúdo completo de um arquivo de imagem, codificado em qualquer formato em que esteja o arquivo de imagem ou em valores de pixel RGB?
Outras respostas aqui mostram como ler um arquivo em um arquivo byte[]. Você byte[]conterá o conteúdo exato do arquivo e você precisará decodificá-lo para fazer qualquer coisa com os dados da imagem.
A API padrão do Java para leitura (e gravação) de imagens é a API ImageIO, que você pode encontrar no pacote javax.imageio. Você pode ler uma imagem de um arquivo com apenas uma única linha de código:
Isso lhe dará um BufferedImage, não um byte[]. Para acessar getRaster()os dados da imagem, você pode acessar o BufferedImage. Isso fornecerá um Rasterobjeto, que possui métodos para acessar os dados de pixel (possui vários getPixel()/ getPixels()métodos).
Pesquisar a documentação da API para javax.imageio.ImageIO, java.awt.image.BufferedImage, java.awt.image.Rasteretc.
O ImageIO suporta vários formatos de imagem por padrão: JPEG, PNG, BMP, WBMP e GIF. É possível adicionar suporte para mais formatos (você precisaria de um plug-in que implemente a interface do provedor de serviços ImageIO).
Digamos, e se a matriz de bytes for muito grande, o que poderia causar OOM para o heap? Existe uma solução semelhante que usará o JNI para armazenar os bytes e, mais tarde, poderemos usar o inputStream a partir dos dados armazenados lá (tipo de cache temporário)?
desenvolvedor android
14
Se você não deseja usar a biblioteca do Apache commons-io, esse trecho é retirado da classe sun.misc.IOUtils. É quase duas vezes mais rápido que a implementação comum usando ByteBuffers:
Essa é uma solução um pouco estranha, o comprimento é um limite superior do comprimento da matriz. Se você conhece o tamanho, tudo o que precisa é: byte [] output = new byte [length]; is.read (saída); (mas veja minha resposta)
Luke Hutchison
@ luke-hutchison como eu disse, esta é a solução do sun.misc.IOUtils. Nos casos mais comuns, você não sabe o tamanho de um InputStream antecipadamente, portanto, se (length == -1) length = Integer.MAX_VALUE; aplica-se. Essa solução funciona, mesmo se o comprimento especificado for maior que o comprimento do InputStream.
Kristian Kraljic 31/07/2015
@LukeHutchison Se você souber o comprimento, poderá lidar com ele com algumas linhas. Se você olhar para cada resposta, todo mundo está reclamando que o comprimento não é conhecido. Finalmente, uma resposta que é padrão, pode ser usada com o Java 7 Android e não requer nenhuma biblioteca externa.
Csaba Toth 27/02
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;}
Depende do tamanho do conhecimento antecipadamente.
amigos estão dizendo sobre stolsvik
2
Claro, mas eles devem saber o tamanho: "Eu quero ler uma imagem"
pihentagy
1
se você souber o tamanho, o java fornecerá o código para você. veja minha resposta ou google para "DataInputStream" e é método readFully.
Dermoritz 28/05
Você deve adicionar is.close()se offset < bytes.lengthou InputStreamnão será fechado se essa exceção for lançada.
Jared Rummler
3
Então é melhor, você deve usar try-with-recursos
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();
No entanto, geralmente o sistema operacional já possui buffers suficientes para que isso não seja uma grande preocupação para arquivos menores. Não é como se a cabeça do disco rígido lesse cada byte separadamente (um disco rígido é uma placa de vidro giratória com informações magnéticas, um pouco como o ícone estranho que usamos para salvar dados: P).
Maarten Bodewes
6
@Maarten Bodewes: a maioria dos dispositivos possui um tipo de transferência de bloco; portanto, nem toda leitura () causa um acesso real ao dispositivo, mas ter uma chamada do SO por byte já é suficiente para diminuir o desempenho. Enquanto terminava o InputStreamem um BufferedInputStreamantes que o código reduziria os-chamadas e mitigar os inconvenientes de desempenho significativamente, que o código ainda vai fazer o trabalho de cópia manual desnecessária de um tampão para outro.
Qual é a diferença entre isso e InputStram.readAllBytes()aquilo é one-liner?
Slava Semushin
2
Sei que é tarde demais, mas aqui acho que é uma solução mais limpa, mais legível ...
/**
* 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();}
Não é apenas \risso que poderia ser um problema. Este método converte os bytes em caracteres e vice-versa (usando o conjunto de caracteres padrão para InputStreamReader). Quaisquer bytes que não sejam válidos na codificação de caracteres padrão (por exemplo, -1 para UTF-8 no Linux) serão corrompidos, possivelmente alterando o número de bytes.
seanf
Parece que esta é uma boa resposta, mas orientada para o texto. Comprador, cuidado.
Wheezil
1
Tentei editar a resposta de @ numan com uma correção para gravar dados de lixo, mas a edição foi rejeitada. Embora esse pequeno pedaço de código não seja nada brilhante, não vejo outra resposta melhor. Aqui está o que faz mais sentido para mim:
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();
btw ByteArrayOutputStream não precisa ser fechado. construções try / finalmente omitidas para facilitar a leitura
É particularmente importante perceber que você não deve usar esse método para dimensionar um contêiner e assumir que é possível ler a totalidade do fluxo sem precisar redimensionar o contêiner. Esses chamadores provavelmente devem escrever tudo o que lêem em um ByteArrayOutputStream e convertê-lo em uma matriz de bytes. Como alternativa, se você estiver lendo um arquivo, File.length retornará o tamanho atual do arquivo (embora suponha que o tamanho do arquivo não possa ser alterado pode estar incorreto, a leitura de um arquivo é inerentemente atrevida).
Embrulhe-o em um DataInputStream, se isso estiver fora da mesa, por algum motivo, use read para martelá-lo até obter um -1 ou todo o bloco que você pediu.
Estamos vendo algum atraso para poucas transações da AWS, ao converter o objeto S3 em ByteArray.
Nota: O objeto S3 é um documento PDF (o tamanho máximo é de 3 mb).
Estamos usando a opção 1 (org.apache.commons.io.IOUtils) para converter o objeto S3 em ByteArray. Observamos que o S3 fornece o método IOUtils do inbuild para converter o objeto S3 em ByteArray, solicitamos que você confirme qual é a melhor maneira de converter o objeto S3 em ByteArray para evitar o atraso.
Opção 1:
import org.apache.commons.io.IOUtils;
is = s3object.getObjectContent();
content =IOUtils.toByteArray(is);
Opção 2:
import com.amazonaws.util.IOUtils;
is = s3object.getObjectContent();
content =IOUtils.toByteArray(is);
Além disso, deixe-me saber se temos outra maneira melhor de converter o objeto s3 para bytearray
O outro caso para obter a matriz de bytes correta via fluxo, após enviar a solicitação ao servidor e aguardar a resposta.
/**
* 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);
Você está fazendo uma cópia extra se usar ByteArrayOutputStream. Se você conhece o tamanho do fluxo antes de começar a lê-lo (por exemplo, o InputStream é na verdade um FileInputStream e pode chamar file.length () no arquivo, ou o InputStream é uma entrada do arquivo zip InputStream e pode chamar zipEntry. length ()), então é muito melhor escrever diretamente na matriz de bytes [] - ele usa metade da memória e economiza tempo.
// 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: a última linha acima lida com arquivos sendo truncados enquanto o fluxo está sendo lido, se você precisar lidar com essa possibilidade, mas se o arquivo ficar mais longo enquanto o fluxo estiver sendo lido, o conteúdo da matriz byte [] não será aumentado para incluir o novo conteúdo do arquivo, a matriz será simplesmente truncada para o comprimento antigo inputStreamLength .
Adicione um pouco de explicação com a resposta de como essa resposta ajuda OP na fixação edição atual
ρяσѕρєя K
0
Esta é minha versão copiar e colar:
@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();}
Embora esse trecho de código possa resolver a questão, incluir uma explicação realmente ajuda a melhorar a qualidade da sua postagem. Lembre-se de que você está respondendo à pergunta dos leitores no futuro e essas pessoas podem não saber os motivos da sua sugestão de código.
precisa saber é o seguinte
0
Java 7 e posterior:
import sun.misc.IOUtils;...InputStream in =...;byte[] buf =IOUtils.readFully(in,-1,false);
sun.misc.IOUtilsnão é "Java 7". É uma classe específica de implementação proprietária que pode não estar presente em outras implementações do JRE e pode desaparecer sem nenhum aviso em um dos próximos releases.
Solução no Kotlin (também funcionará em Java, é claro), que inclui os dois casos em que você sabe o tamanho ou não:
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}}
Se você souber o tamanho, poupará o dobro da memória usada em comparação com as outras soluções (em um breve momento, mas ainda pode ser útil). Isso porque você precisa ler o fluxo inteiro até o final e depois convertê-lo em uma matriz de bytes (semelhante ao ArrayList que você converte em apenas uma matriz).
Portanto, se você estiver no Android, por exemplo, e tiver um Uri para lidar, tente obter o tamanho usando este:
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();}
Fechar e liberar bos é um desperdício de cliques no teclado. Fechar o fluxo de entrada tem mais chances de ajudar. Ler um byte de cada vez é ineficiente. Veja a resposta de numan.
Respostas:
Você pode usar o Apache Commons IO para lidar com essa e outras tarefas semelhantes.
O
IOUtils
tipo possui um método estático para lerInputStream
e retornar abyte[]
.Internamente, isso cria ae
ByteArrayOutputStream
copia os bytes para a saída e depois chamatoByteArray()
. Ele lida com arquivos grandes, copiando os bytes em blocos de 4KiB.fonte
FastArrayList
seus mapas de referência suaves e fracos, e voltar para me dizer como esta biblioteca é "bem testada". É uma pilha de lixoInputStream is;
byte[] filedata=ByteStreams.toByteArray(is);
Você precisa ler cada byte do seu
InputStream
e gravá-lo em aByteArrayOutputStream
.Você pode recuperar a matriz de bytes subjacente chamando
toByteArray()
:fonte
Finalmente, depois de vinte anos, há uma solução simples sem a necessidade de uma biblioteca de terceiros, graças ao Java 9 :
Observe também os métodos de conveniência
readNBytes(byte[] b, int off, int len)
etransferTo(OutputStream)
as necessidades recorrentes.fonte
Use baunilha Java
DataInputStream
e seureadFully
método (existe desde pelo menos Java 1.4):Existem outros tipos desse método, mas eu uso isso o tempo todo para este caso de uso.
fonte
DataInputStream
é usada principalmente para ler tipos primários (Longs, Shorts, Chars ...) de um fluxo, para que possamos ver esse uso como um uso indevido da classe.InputStream.read
.Se você usar google goiaba , será tão simples quanto:
fonte
ByteStreams
é anotado com@Beta
Como sempre, também o framework Spring (core desde 3.2.2) tem algo para você:
StreamUtils.copyToByteArray()
fonte
fonte
Solução segura (com capacidade de
close
fluxos corretamente):Versão Java 9+:
Versão Java 8:
Versão Kotlin (quando o Java 9+ não está acessível):
Para evitar aninhados,
use
veja aqui .fonte
Você realmente precisa da imagem como um
byte[]
? O que exatamente você espera nobyte[]
- o conteúdo completo de um arquivo de imagem, codificado em qualquer formato em que esteja o arquivo de imagem ou em valores de pixel RGB?Outras respostas aqui mostram como ler um arquivo em um arquivo
byte[]
. Vocêbyte[]
conterá o conteúdo exato do arquivo e você precisará decodificá-lo para fazer qualquer coisa com os dados da imagem.A API padrão do Java para leitura (e gravação) de imagens é a API ImageIO, que você pode encontrar no pacote
javax.imageio
. Você pode ler uma imagem de um arquivo com apenas uma única linha de código:Isso lhe dará um
BufferedImage
, não umbyte[]
. Para acessargetRaster()
os dados da imagem, você pode acessar oBufferedImage
. Isso fornecerá umRaster
objeto, que possui métodos para acessar os dados de pixel (possui váriosgetPixel()
/getPixels()
métodos).Pesquisar a documentação da API para
javax.imageio.ImageIO
,java.awt.image.BufferedImage
,java.awt.image.Raster
etc.O ImageIO suporta vários formatos de imagem por padrão: JPEG, PNG, BMP, WBMP e GIF. É possível adicionar suporte para mais formatos (você precisaria de um plug-in que implemente a interface do provedor de serviços ImageIO).
Consulte também o seguinte tutorial: Trabalhando com imagens
fonte
No caso de alguém ainda estar procurando uma solução sem dependência e se você tiver um arquivo .
fonte
Se você não deseja usar a biblioteca do Apache commons-io, esse trecho é retirado da classe sun.misc.IOUtils. É quase duas vezes mais rápido que a implementação comum usando ByteBuffers:
fonte
fonte
@ Adamski: Você pode evitar o buffer inteiramente.
Código copiado de http://www.exampledepot.com/egs/java.io/File2ByteArray.html (Sim, é muito detalhado, mas precisa da metade do tamanho da memória que a outra solução.)
fonte
is.close()
seoffset < bytes.length
ouInputStream
não será fechado se essa exceção for lançada.fonte
InputStream
em umBufferedInputStream
antes que o código reduziria os-chamadas e mitigar os inconvenientes de desempenho significativamente, que o código ainda vai fazer o trabalho de cópia manual desnecessária de um tampão para outro.O Java 9 finalmente fornecerá um bom método:
fonte
InputStram.readAllBytes()
aquilo é one-liner?Sei que é tarde demais, mas aqui acho que é uma solução mais limpa, mais legível ...
fonte
Modo Java 8 (graças a BufferedReader e Adam Bien )
Observe que esta solução limpa o retorno de carro ('\ r') e pode ser inapropriada.
fonte
String
. OP está pedindobyte[]
.\r
isso que poderia ser um problema. Este método converte os bytes em caracteres e vice-versa (usando o conjunto de caracteres padrão para InputStreamReader). Quaisquer bytes que não sejam válidos na codificação de caracteres padrão (por exemplo, -1 para UTF-8 no Linux) serão corrompidos, possivelmente alterando o número de bytes.Tentei editar a resposta de @ numan com uma correção para gravar dados de lixo, mas a edição foi rejeitada. Embora esse pequeno pedaço de código não seja nada brilhante, não vejo outra resposta melhor. Aqui está o que faz mais sentido para mim:
btw ByteArrayOutputStream não precisa ser fechado. construções try / finalmente omitidas para facilitar a leitura
fonte
Veja a
InputStream.available()
documentação:fonte
Embrulhe-o em um DataInputStream, se isso estiver fora da mesa, por algum motivo, use read para martelá-lo até obter um -1 ou todo o bloco que você pediu.
fonte
Estamos vendo algum atraso para poucas transações da AWS, ao converter o objeto S3 em ByteArray.
Nota: O objeto S3 é um documento PDF (o tamanho máximo é de 3 mb).
Estamos usando a opção 1 (org.apache.commons.io.IOUtils) para converter o objeto S3 em ByteArray. Observamos que o S3 fornece o método IOUtils do inbuild para converter o objeto S3 em ByteArray, solicitamos que você confirme qual é a melhor maneira de converter o objeto S3 em ByteArray para evitar o atraso.
Opção 1:
Opção 2:
Além disso, deixe-me saber se temos outra maneira melhor de converter o objeto s3 para bytearray
fonte
O outro caso para obter a matriz de bytes correta via fluxo, após enviar a solicitação ao servidor e aguardar a resposta.
fonte
Você está fazendo uma cópia extra se usar ByteArrayOutputStream. Se você conhece o tamanho do fluxo antes de começar a lê-lo (por exemplo, o InputStream é na verdade um FileInputStream e pode chamar file.length () no arquivo, ou o InputStream é uma entrada do arquivo zip InputStream e pode chamar zipEntry. length ()), então é muito melhor escrever diretamente na matriz de bytes [] - ele usa metade da memória e economiza tempo.
Nota: a última linha acima lida com arquivos sendo truncados enquanto o fluxo está sendo lido, se você precisar lidar com essa possibilidade, mas se o arquivo ficar mais longo enquanto o fluxo estiver sendo lido, o conteúdo da matriz byte [] não será aumentado para incluir o novo conteúdo do arquivo, a matriz será simplesmente truncada para o comprimento antigo inputStreamLength .
fonte
Eu uso isso.
fonte
Esta é minha versão copiar e colar:
fonte
Java 7 e posterior:
fonte
sun.misc.IOUtils
não é "Java 7". É uma classe específica de implementação proprietária que pode não estar presente em outras implementações do JRE e pode desaparecer sem nenhum aviso em um dos próximos releases.Você pode experimentar o Cactoos :
fonte
Aqui está uma versão otimizada, que tenta evitar o máximo possível de copiar bytes de dados:
fonte
Solução no Kotlin (também funcionará em Java, é claro), que inclui os dois casos em que você sabe o tamanho ou não:
Se você souber o tamanho, poupará o dobro da memória usada em comparação com as outras soluções (em um breve momento, mas ainda pode ser útil). Isso porque você precisa ler o fluxo inteiro até o final e depois convertê-lo em uma matriz de bytes (semelhante ao ArrayList que você converte em apenas uma matriz).
Portanto, se você estiver no Android, por exemplo, e tiver um Uri para lidar, tente obter o tamanho usando este:
fonte
fonte