Domanda

Come faccio a leggere un intero InputStream in una matrice di byte?

È stato utile?

Soluzione

È possibile utilizzare Apache Commons IO per gestire questa e simili attività.

Il tipo IOUtils ha un metodo statico per leggere un InputStream e restituire una byte[].

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

Internamente questo crea un ByteArrayOutputStream e copia i byte per l'uscita, poi chiama toByteArray(). Gestisce file di grandi dimensioni copiando i byte in blocchi di 4KiB.

Altri suggerimenti

Hai bisogno di leggere ogni byte dal InputStream e scrivere ad un ByteArrayOutputStream. È quindi possibile recuperare la matrice di byte sottostante chiamando toByteArray(); per es.

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();

Infine, dopo venti anni, c'è una soluzione semplice senza la necessità di una libreria di terze parti, grazie a Java 9 :

InputStream is;
…
byte[] array = is.readAllBytes();

Nota anche i metodi di convenienza readNBytes(byte[] b, int off, int len) e transferTo(OutputStream) soddisfare le esigenze dei ricorrenti

DataInputStream Usa vaniglia Java e il suo metodo readFully (esiste almeno dal Java 1.4):

...
byte[] bytes = new byte[(int) file.length()];
DataInputStream dis = new DataInputStream(new FileInputStream(file));
dis.readFully(bytes);
...

Ci sono alcuni altri sapori di questo metodo, ma io uso questo tutto il tempo per questo caso d'uso.

Se vi capita di usare google guava , sarà semplice come:

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

Come sempre, anche framework Spring (primavera-core dal 3.2.2) ha qualcosa per voi: 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();
}

Avete veramente bisogno l'immagine come byte[]? Che cosa esattamente cosa si aspetta nel byte[] -? L'intero contenuto di un file di immagine, codificato in qualsiasi formato file di immagine è in, o valori dei pixel RGB

Altre risposte qui si mostrano come leggere un file in un byte[]. Il tuo byte[] conterrà il contenuto esatto del file, e avresti bisogno di decodificare che a fare qualsiasi cosa con i dati dell'immagine.

API standard di Java per la lettura (e scrittura) immagini è l'API ImageIO, che potete trovare nella javax.imageio pacchetto. Si può leggere in un'immagine da un file con una sola riga di codice:

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

Questo vi darà un BufferedImage, non un byte[]. Per ottenere i dati di immagine, è possibile chiamare getRaster() sul BufferedImage. Questo vi darà un oggetto Raster, che dispone di metodi per accedere ai dati dei pixel (che ha diversi metodi getPixel() / getPixels()).

Lookup la documentazione delle API per javax.imageio.ImageIO, java.awt.image.BufferedImage, java.awt.image.Raster etc.

ImageIO supporta una serie di formati di immagine per impostazione predefinita: JPEG, PNG, BMP, WBMP e GIF. E 'possibile aggiungere il supporto per più formati (avresti bisogno di un plug-in che implementa l'interfaccia provider di servizi ImageIO).

Si veda anche il seguente tutorial: Lavorare con le immagini

Se non si desidera utilizzare la libreria Apache commons-io, questo frammento è tratto dalla classe sun.misc.IOUtils. E 'quasi due volte più veloce l'attuazione comune utilizzando 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;
}

Nel caso qualcuno è ancora alla ricerca di una soluzione, senza una dipendenza e Se si dispone di un file .

  

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);

sicurezza Soluzione (con capacità di close flussi correttamente):

  • Java 9+ versione:

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

    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 versione (quando Java 9+ non è accessibile):

    @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()
        }
    }
    

    Per evitare use nidificato vedere qui .

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:. È possibile evitare del tutto di buffer

Codice copiato da http://www.exampledepot.com/egs/java.io/File2ByteArray. html (Sì, è molto verboso, ma ha bisogno la metà delle dimensioni della memoria come l'altra soluzione.)

// 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 vi darà finalmente un metodo piacevole:

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

Lo so che è troppo tardi, ma qui penso che è la soluzione più pulita che è più leggibile ...

/**
 * 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 (grazie 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 che questa soluzione salviette di ritorno a capo (' ') e può essere inappropriato.

Ho provato a modificare @ risposta di Numan con una correzione per la scrittura di caratteri privi di significato, ma modifica è stata respinta. Mentre questo breve pezzo di codice è niente di eccezionale non riesco a vedere qualsiasi altra risposta migliore. Ecco ciò che rende più senso per me:

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 non deve essere chiuso. try / finally costrutti omesso per migliorare la leggibilità

Vedere la documentazione InputStream.available():

  

E 'particolarmente importante rendersi conto che non è necessario utilizzare questo   metodo per dimensioni di un contenitore e supponiamo che si può leggere l'interezza   del torrente senza la necessità di ridimensionare il contenitore. tali chiamanti   dovrebbe probabilmente scrivere tutto quello che leggono ad un ByteArrayOutputStream   e convertire in un array di byte. In alternativa, se stai leggendo   da un file, file.length restituisce la lunghezza corrente del file   (Anche se supponendo che la lunghezza del file non può cambiare non può essere corretto,   lettura di un file è intrinsecamente filante).

Java 7 e versioni successive:

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

L'altro caso per ottenere corretto array di byte via streaming, dopo invia una richiesta al server e di attesa per la risposta.

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

Si sta facendo una copia in più se si utilizza ByteArrayOutputStream. Se si conosce la lunghezza del flusso prima di iniziare a leggerlo (ad esempio, l'InputStream è in realtà un FileInputStream, ed è possibile chiamare file.length () sul file, oppure l'InputStream è una voce file zip InputStream, ed è possibile chiamare ZipEntry. lunghezza ()), quindi è molto meglio scrivere direttamente nel byte [] array -. usa metà della memoria, e risparmiare 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. l'ultima riga sopra offerte con i file sempre troncato mentre il flusso viene letto, se è necessario gestire questa possibilità, ma se il file viene più , mentre il flusso viene letta, il contenuto del byte [ ] array non verrà allungato per includere il nuovo contenuto del file, l'array sarà semplicemente troncato al vecchio lunghezza di inputStreamLength .

Io uso questa.

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

Questa è la mia versione di copia-incolla:

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

avvolgerla in un DataInputStream se questo è fuori dal tavolo per qualche ragione, basta usare leggere a martello su di esso fino a quando non ti dà un -1 o l'intero blocco che hai chiesto.

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;
}
:

È possibile provare Cactoos :

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

Stiamo assistendo a un certo ritardo per alcune transazioni AWS, durante la conversione oggetto S3 per ByteArray.

. Nota: S3 oggetto è documento PDF (dimensione massima è di 3 MB)

Stiamo usando l'opzione # 1 (org.apache.commons.io.IOUtils) per convertire l'oggetto S3 a ByteArray. Abbiamo notato S3 fornisce il metodo IOUtils inbuild per convertire l'oggetto S3 per ByteArray, stiamo chiediamo di confermare qual è il modo migliore per convertire l'oggetto S3 per ByteArray per evitare il ritardo.

Opzione # 1:

import org.apache.commons.io.IOUtils;
is = s3object.getObjectContent();
content =IOUtils.toByteArray(is);

Opzione # 2:

import com.amazonaws.util.IOUtils;
is = s3object.getObjectContent();
content =IOUtils.toByteArray(is);

Inoltre vorrei sapere se abbiamo qualche altro modo migliore per convertire l'oggetto s3 a ByteArray

Questa è una versione ottimizzata, che cerca di evitare la copia dei dati byte, per quanto possibile:

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

Questo funziona per me,

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;
    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top