Respostas:
Você pode usar o Apache Commons IO para lidar com essa e outras tarefas semelhantes.
O IOUtilstipo possui um método estático para ler InputStreame retornar a byte[].
InputStream is;
byte[] bytes = IOUtils.toByteArray(is);
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.
FastArrayListseus mapas de referência suaves e fracos, e voltar para me dizer como esta biblioteca é "bem testada". É uma pilha de lixo
InputStream is; byte[] filedata=ByteStreams.toByteArray(is);
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 = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
return buffer.toByteArray();
Finalmente, depois de vinte anos, há uma solução simples sem a necessidade de uma biblioteca de terceiros, graças ao Java 9 :
InputStream is;
…
byte[] array = is.readAllBytes();
Observe também os métodos de conveniência readNBytes(byte[] b, int off, int len)e transferTo(OutputStream)as necessidades recorrentes.
Use baunilha Java DataInputStreame seu readFullymétodo (existe desde pelo menos Java 1.4):
...
byte[] bytes = new byte[(int) file.length()];
DataInputStream dis = new DataInputStream(new FileInputStream(file));
dis.readFully(bytes);
...
Existem outros tipos desse método, mas eu uso isso o tempo todo para este caso de uso.
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:
byte[] bytes = ByteStreams.toByteArray(inputStream);
ByteStreamsé anotado com@Beta
Como sempre, também o framework Spring (core desde 3.2.2) tem algo para você:StreamUtils.copyToByteArray()
public static byte[] getBytesFromInputStream(InputStream is) throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
byte[] buffer = new byte[0xFFFF];
for (int len = is.read(buffer); len != -1; len = is.read(buffer)) {
os.write(buffer, 0, len);
}
return os.toByteArray();
}
Solução segura (com capacidade declosefluxos corretamente):
Versão Java 9+:
final byte[] bytes;
try (inputStream) {
bytes = inputStream.readAllBytes();
}Versão Java 8:
public static byte[] readAllBytes(InputStream inputStream) throws IOException {
final int bufLen = 4 * 0x400; // 4KB
byte[] buf = new byte[bufLen];
int readLen;
IOException exception = null;
try {
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
while ((readLen = inputStream.read(buf, 0, bufLen)) != -1)
outputStream.write(buf, 0, readLen);
return outputStream.toByteArray();
}
} catch (IOException e) {
exception = e;
throw e;
} finally {
if (exception == null) inputStream.close();
else try {
inputStream.close();
} catch (IOException e) {
exception.addSuppressed(e);
}
}
}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 = 0
ByteArrayOutputStream().use { o ->
this.use { i ->
while (i.read(buf, 0, bufLen).also { readLen = it } != -1)
o.write(buf, 0, readLen)
}
return o.toByteArray()
}
}
Para evitar aninhados, useveja aqui .
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:
BufferedImage image = ImageIO.read(new File("image.jpg"));
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).
Consulte também o seguinte tutorial: Trabalhando com imagens
No caso de alguém ainda estar procurando uma solução sem dependência e se você tiver um arquivo .
1) DataInputStream
byte[] data = new byte[(int) file.length()];
DataInputStream dis = new DataInputStream(new FileInputStream(file));
dis.readFully(data);
dis.close();
2) ByteArrayOutputStream
InputStream is = new FileInputStream(file);
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[(int) file.length()];
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
3) RandomAccessFile
RandomAccessFile raf = new RandomAccessFile(file, "r");
byte[] data = new byte[(int) raf.length()];
raf.readFully(data);
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:
public static byte[] readFully(InputStream is, int length, boolean readAll)
throws IOException {
byte[] output = {};
if (length == -1) length = Integer.MAX_VALUE;
int pos = 0;
while (pos < length) {
int bytesToRead;
if (pos >= output.length) { // Only expand when there's no room
bytesToRead = Math.min(length - pos, output.length + 1024);
if (output.length < pos + bytesToRead) {
output = Arrays.copyOf(output, pos + bytesToRead);
}
} else {
bytesToRead = output.length - pos;
}
int cc = is.read(output, pos, bytesToRead);
if (cc < 0) {
if (readAll && length != Integer.MAX_VALUE) {
throw new EOFException("Detect premature EOF");
} else {
if (output.length != pos) {
output = Arrays.copyOf(output, pos);
}
break;
}
}
pos += cc;
}
return output;
}
@ 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.)
// Returns the contents of the file in a byte array.
public static byte[] getBytesFromFile(File file) throws IOException {
InputStream is = new FileInputStream(file);
// Get the size of the file
long 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 data
byte[] bytes = new byte[(int)length];
// Read in the bytes
int 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 in
if (offset < bytes.length) {
throw new IOException("Could not completely read file "+file.getName());
}
// Close the input stream and return bytes
is.close();
return bytes;
}
is.close()se offset < bytes.lengthou InputStreamnão será fechado se essa exceção for lançada.
Input Stream is ...
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int next = in.read();
while (next > -1) {
bos.write(next);
next = in.read();
}
bos.flush();
byte[] result = bos.toByteArray();
bos.close();
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.
O Java 9 finalmente fornecerá um bom método:
InputStream in = ...;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
in.transferTo( bos );
byte[] bytes = bos.toByteArray();
InputStram.readAllBytes()aquilo é one-liner?
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.
*/
public static byte[] streamToByteArray(InputStream stream) throws IOException {
byte[] buffer = new byte[1024];
ByteArrayOutputStream os = new ByteArrayOutputStream();
int line = 0;
// read bytes from stream, and store them in buffer
while ((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();
}
Modo Java 8 (graças a BufferedReader e Adam Bien )
private static byte[] readFully(InputStream input) throws IOException {
try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input))) {
return buffer.lines().collect(Collectors.joining("\n")).getBytes(<charset_can_be_specified>);
}
}
Observe que esta solução limpa o retorno de carro ('\ r') e pode ser inapropriada.
String. OP está pedindo byte[].
\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.
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 = new ByteArrayOutputStream();
byte[] buffer = new byte[1024]; // you can configure the buffer size
int length;
while ((length = in.read(buffer)) != -1) out.write(buffer, 0, length); //copy streams
in.close(); // call this in a finally block
byte[] result = out.toByteArray();
btw ByteArrayOutputStream não precisa ser fechado. construções try / finalmente omitidas para facilitar a leitura
Veja a InputStream.available()documentação:
É 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.
public int readFully(InputStream in, byte[] data) throws IOException {
int offset = 0;
int bytesRead;
boolean read = false;
while ((bytesRead = in.read(data, offset, data.length - offset)) != -1) {
read = true;
offset += bytesRead;
if (offset >= data.length) {
break;
}
}
return (read) ? offset : -1;
}
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 = new Socket(IP, port);
// mSocket.setSoTimeout(30000);
DataOutputStream mDos = new DataOutputStream(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 = new DataInputStream(mSocket.getInputStream());
byte[] data = new byte[mDis.available()];
// Collecting data into byte array
for (int i = 0; i < data.length; i++)
data[i] = mDis.readByte();
// Converting collected data in byte array into String.
String RESPONSE = new String(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[] array
byte[] buf = new byte[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 operation
byte[] 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 .
Eu uso isso.
public static byte[] toByteArray(InputStream is) throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
byte[] b = new byte[4096];
int n = 0;
while ((n = is.read(b)) != -1) {
output.write(b, 0, n);
}
return output.toByteArray();
} finally {
output.close();
}
}
Esta é minha versão copiar e colar:
@SuppressWarnings("empty-statement")
public static byte[] inputStreamToByte(InputStream is) throws IOException {
if (is == null) {
return null;
}
// Define a size if you have an idea of it.
ByteArrayOutputStream r = new ByteArrayOutputStream(2048);
byte[] read = new byte[512]; // Your buffer size.
for (int i; -1 != (i = is.read(read)); r.write(read, 0, i));
is.close();
return r.toByteArray();
}
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.
Aqui está uma versão otimizada, que tenta evitar o máximo possível de copiar bytes de dados:
private static byte[] loadStream (InputStream stream) throws IOException {
int available = stream.available();
int expectedSize = available > 0 ? available : -1;
return loadStream(stream, expectedSize);
}
private static byte[] loadStream (InputStream stream, int expectedSize) throws IOException {
int basicBufferSize = 0x4000;
int initialBufferSize = (expectedSize >= 0) ? expectedSize : basicBufferSize;
byte[] buf = new byte[initialBufferSize];
int pos = 0;
while (true) {
if (pos == buf.length) {
int readAhead = -1;
if (pos == expectedSize) {
readAhead = stream.read(); // test whether EOF is at expectedSize
if (readAhead == -1) {
return buf;
}
}
int newBufferSize = Math.max(2 * buf.length, basicBufferSize);
buf = Arrays.copyOf(buf, newBufferSize);
if (readAhead != -1) {
buf[pos++] = (byte)readAhead;
}
}
int len = stream.read(buf, pos, buf.length - pos);
if (len < 0) {
return Arrays.copyOf(buf, pos);
}
pos += len;
}
}
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 -> null
else -> {
val sizeInt = size.toInt()
val result = ByteArray(sizeInt)
readBytesIntoByteArray(result, sizeInt)
result
}
}
}
fun InputStream.readBytesIntoByteArray(byteArray: ByteArray,bytesToRead:Int=byteArray.size) {
var offset = 0
while (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/878126
FileUtilEx.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 = 0L
while (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 = new ByteArrayOutputStream();
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();
}