Pergunta

Como faço para ler um InputStream inteiro em uma matriz de bytes?

Foi útil?

Solução

Você pode usar o Apache Commons IO para lidar com este e semelhantes tarefas.

O tipo IOUtils tem um método estático para ler um InputStream e retornar um byte[].

InputStream is;
byte[] bytes = IOUtils.toByteArray(is);

Internamente, isso cria uma ByteArrayOutputStream e copia os bytes para a saída, em seguida, chama toByteArray(). Ele lida com arquivos grandes, copiando os bytes em blocos de 4KiB.

Outras dicas

Você precisa ler cada byte do seu InputStream e escrevê-lo a um ByteArrayOutputStream. Você pode recuperar a matriz de bytes subjacentes chamando toByteArray(); por exemplo.

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 parte 3, graças a 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) abordar as necessidades recorrentes

DataInputStream Use Java de baunilha e sua readFully Method (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 alguns outros sabores de este método, mas eu uso isso o tempo todo para este caso de uso.

Se acontecer de você usar google goiaba , vai ser tão simples como:

byte[] bytes = ByteStreams.toByteArray(inputStream);

Como sempre, também Primavera quadro (primavera-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();
}

Você realmente precisa a imagem como um byte[]? O que exatamente você espera na byte[]? - o conteúdo completo de um arquivo de imagem, codificada em qualquer formato do arquivo de imagem se encontra, ou valores de pixel RGB

Outras respostas aqui mostrar-lhe como ler um arquivo em um byte[]. Seu byte[] irá conter o conteúdo exato do arquivo, e você precisaria de decodificação que fazer alguma coisa com os dados da imagem.

API padrão do Java para leitura (e escrever) imagens é a API ImageIO, que você pode encontrar no javax.imageio pacote. Você pode ler em uma imagem de um arquivo com apenas uma única linha de código:

BufferedImage image = ImageIO.read(new File("image.jpg"));

Isto lhe dará uma BufferedImage, não um byte[]. Para obter os dados de imagem, você pode chamar getRaster() na BufferedImage. Isto lhe dará um objeto Raster, que tem métodos para acessar os dados de pixel (que tem vários métodos getPixel() / getPixels()).

Lookup a documentação da API para javax.imageio.ImageIO, java.awt.image.BufferedImage, java.awt.image.Raster etc.

ImageIO suporta um número de formatos de imagem por padrão: JPEG, PNG, BMP, WBMP e GIF. É possível adicionar suporte para mais formatos (você precisa de um plug-in que implementa a interface provedor de serviços ImageIO).

Veja também o seguinte tutorial: trabalhar com imagens

Se você não quiser usar o Apache commons-io biblioteca, 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;
}

Em caso alguém está ainda à procura de uma solução sem uma dependência e Se você tem 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);

Seguro Solução (com capacidade de close córregos corretamente):

  • versão Java com mais de 9:

    final byte[] bytes;
    try (inputStream) {
        bytes = inputStream.readAllBytes();
    }
    
  • Java 8 versão:

    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);
            }
        }
    }
    
  • Kotlin version (quando Java 9+ não é 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 use aninhada ver aqui .

ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
while (true) {
    int r = in.read(buffer);
    if (r == -1) break;
    out.write(buffer, 0, r);
}

byte[] ret = out.toByteArray();

@Adamski:. Você pode evitar tampão inteiramente

Código copiado de http://www.exampledepot.com/egs/java.io/File2ByteArray. html (Sim, é muito detalhado, mas precisa de metade do tamanho da memória como 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;
}
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();

Java 9 vai lhe dar, finalmente, um bom método:

InputStream in = ...;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
in.transferTo( bos );
byte[] bytes = bos.toByteArray();

Eu sei que é tarde demais, mas aqui eu acho que é solução mais limpa que é 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();
}

Java 8 vias (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>);
    }
}

Nota que esta solução toalhetes retorno de carro ( '\ r') e pode ser inadequada.

Eu tentei editar resposta da @ Numan com uma correção para escrever dados de lixo, mas edição foi rejeitada. Embora este pequeno pedaço de código não é nada brilhante que eu não consigo ver nenhuma 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 necessidade ByteArrayOutputStream não ser fechado. tente / finally construções omitidos para facilitar a leitura

Consulte a documentação InputStream.available():

É particularmente importante perceber que você não deve usar este método para o tamanho de um recipiente e assumir que você pode ler a totalidade do fluxo sem a necessidade de redimensionar o recipiente. tais chamadores provavelmente deve escrever tudo o que lêem a um ByteArrayOutputStream e convertê-lo em uma matriz de bytes. Alternativamente, se você estiver lendo de um arquivo, file.length retorna o comprimento atual do arquivo (Embora assumindo que o comprimento do arquivo não pode mudar pode estar incorreta, lendo um arquivo é inerentemente atrevido).

Java 7 e posterior:

import sun.misc.IOUtils;
...
InputStream in = ...;
byte[] buf = IOUtils.readFully(in, -1, false);

O outro caso para obter matriz de bytes correta via stream, após pedido de envio para o servidor e esperando 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 você usar ByteArrayOutputStream. Se você souber o comprimento do fluxo antes de começar a lê-lo (por exemplo, o InputStream é realmente um FileInputStream, e você pode chamar file.length () no arquivo, ou o InputStream é uma InputStream entrada zipfile, e você pode chamar ZipEntry. length ()), então é muito melhor para escrever diretamente para a matriz byte [] -. 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);

NB. a última linha acima lida com arquivos ficar truncado enquanto o fluxo está sendo lido, se você precisa lidar com essa possibilidade, mas se o arquivo fica mais enquanto o fluxo está sendo lido, o conteúdo do byte [ ] array não vai ser aumentado para incluir o novo conteúdo do arquivo, a matriz será simplesmente truncada para o comprimento de idade 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();
}

envolvê-la em um DataInputStream se isso está fora da mesa, por algum motivo, basta usar ler a martelo sobre ele até que ele lhe dá 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;
}

Você pode tentar Cactoos :

byte[] array = new BytesOf(stream).bytes();

Estamos vendo algum atraso para poucos transação AWS, ao converter S3 objeto ByteArray.

Nota:. S3 objeto é documento PDF (tamanho máximo é de 3 mb)

Estamos usando a opção # 1 (org.apache.commons.io.IOUtils) para converter o objeto S3 para ByteArray. Temos notado S3 fornecer o método IOUtils inbuild para converter o objeto S3 para ByteArray, estamos pedir-lhe para confirmar qual é a melhor maneira de converter o objeto S3 para 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);

Também deixe-me saber se temos alguma outra maneira melhor para converter o objeto s3 para bytearray

Aqui está uma versão otimizada, que tenta evitar a cópia de bytes de dados, tanto quanto possível:

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;
   }
}
/*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();
}

Isso funciona para mim,

if(inputStream != null){
                ByteArrayOutputStream contentStream = readSourceContent(inputStream);
                String stringContent = contentStream.toString();
                byte[] byteArr = encodeString(stringContent);
            }

readSourceContent ()

public static ByteArrayOutputStream readSourceContent(InputStream inputStream) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        int nextChar;
        try {
            while ((nextChar = inputStream.read()) != -1) {
                outputStream.write(nextChar);
            }
            outputStream.flush();
        } catch (IOException e) {
            throw new IOException("Exception occurred while reading content", e);
        }

        return outputStream;
    }

encodeString ()

public static byte[] encodeString(String content) throws UnsupportedEncodingException {
        byte[] bytes;
        try {
            bytes = content.getBytes();

        } catch (UnsupportedEncodingException e) {
            String msg = ENCODING + " is unsupported encoding type";
            log.error(msg,e);
            throw new UnsupportedEncodingException(msg, e);
        }
        return bytes;
    }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top