web-dev-qa-db-ger.com

Konvertieren Sie InputStream in Java in ein Byte-Array

Wie lese ich eine ganze InputStream in ein Byte-Array?

750
JGC

Sie können Apache Commons IO verwenden, um diese und ähnliche Aufgaben auszuführen.

Der Typ IOUtils verfügt über eine statische Methode, um eine InputStream zu lesen und einen byte[] zurückzugeben.

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

Intern wird eine ByteArrayOutputStream erstellt, die Bytes werden in die Ausgabe kopiert und dann toByteArray() aufgerufen. Es verarbeitet große Dateien, indem die Bytes in 4-KB-Blöcken kopiert werden.

1019
Rich Seller

Sie müssen jedes Byte aus Ihrer InputStream lesen und in eine ByteArrayOutputStream schreiben. Sie können dann das zugrunde liegende Byte-Array abrufen, indem Sie toByteArray() aufrufen. z.B.

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

Endlich, nach zwanzig Jahren, gibt es dank Java 9 eine einfache Lösung ohne die Notwendigkeit einer Drittanbieter-Bibliothek.

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

Beachten Sie auch die Komfortmethoden readNBytes(byte[] b, int off, int len) und transferTo(OutputStream) , die auf wiederkehrende Anforderungen eingehen.

230
Holger

Verwenden Sie Vanilla Javas DataInputStream und seine readFully-Methode (existiert seit mindestens Java 1.4):

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

Es gibt einige andere Varianten dieser Methode, aber ich verwende diese ständig für diesen Anwendungsfall.

113
dermoritz

Wenn Sie google guava verwenden, ist es so einfach wie:

byte[] bytes = ByteStreams.toByteArray(inputStream);
112
bertie
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();
}
37
oliverkn

Wie immer hat auch Spring Framework (Spring-Core seit 3.2.2) etwas für Sie: StreamUtils.copyToByteArray()

34
Arne Burmeister

Benötigen Sie das Bild wirklich als byte[]? Was genau erwarten Sie im byte[] - dem vollständigen Inhalt einer Bilddatei, codiert in dem Format, in dem sich die Bilddatei befindet, oder RGB-Pixelwerten?

Weitere Antworten zeigen Ihnen, wie Sie eine Datei in einen byte[] lesen. Ihr byte[] enthält den genauen Inhalt der Datei, und Sie müssen diesen dekodieren, um mit den Bilddaten zu arbeiten.

Javas Standard-API zum Lesen (und Schreiben) von Bildern ist die ImageIO-API, die Sie im Paket javax.imageio finden. Sie können ein Bild aus einer Datei mit nur einer einzigen Codezeile einlesen:

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

Dadurch erhalten Sie eine BufferedImage und keinen byte[]. Um an die Bilddaten zu gelangen, können Sie getRaster() über die BufferedImage aufrufen. Dadurch erhalten Sie ein Raster-Objekt, das über Methoden zum Zugriff auf die Pixeldaten verfügt (es verfügt über mehrere getPixel()/getPixels()-Methoden).

Schlagen Sie in der API-Dokumentation nach javax.imageio.ImageIO, Java.awt.image.BufferedImage, Java.awt.image.Raster usw. nach.

ImageIO unterstützt standardmäßig eine Reihe von Bildformaten: JPEG, PNG, BMP, WBMP und GIF. Es ist möglich, Unterstützung für weitere Formate hinzuzufügen (Sie benötigen ein Plug-In, das die ImageIO-Service-Provider-Schnittstelle implementiert).

Siehe auch das folgende Tutorial: Arbeiten mit Bildern

20
Jesper

Wenn Sie die Apache Commons-io-Bibliothek nicht verwenden möchten, wird dieses Snippet aus der Sun.misc.IOUtils-Klasse übernommen. Es ist fast doppelt so schnell wie die übliche Implementierung mit 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;
}
14

Falls jemand noch nach einer Lösung ohne Abhängigkeit sucht und wenn Sie eine Datei .

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);
12
harsh_v
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();
9
YulCheney

@Adamski: Du kannst Puffer ganz vermeiden.

Code kopiert von http://www.exampledepot.com/egs/Java.io/File2ByteArray.html (Ja, es ist sehr ausführlich, benötigt jedoch die Hälfte des Speichers als die andere Lösung.)

// 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;
}
8
pihentagy
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();
8
Aturio

Safe Lösung (mit der Möglichkeit, close Streams korrekt auszuführen):

  • Java 9+ Version:

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

    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 (kompatibel mit Java ≤8):

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

    Um verschachtelte use zu vermeiden, siehe hier .

4
Mir-Ismaili

Java 9 gibt Ihnen endlich eine schöne Methode:

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

Ich weiß, dass es zu spät ist, aber ich denke, dass eine sauberere Lösung besser lesbar ist ...

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

Java 7 und höher:

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

Java 8-Weg (Dank an BufferedReader und 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>);
    }
}

Beachten Sie, dass diese Lösung Wagenrücklauf ('\ r') löscht und ungeeignet sein kann.

1
Ilya Bystrov

Siehe die InputStream.available() Dokumentation:

Es ist besonders wichtig zu wissen, dass Sie dies nicht verwenden dürfen Methode, um die Größe eines Containers zu ändern und davon auszugehen, dass Sie die Gesamtheit lesen können des Streams, ohne dass die Größe des Containers geändert werden muss. Solche Anrufer sollte wahrscheinlich alles, was sie lesen, in einen ByteArrayOutputStream .__ schreiben. und konvertieren Sie das in ein Byte-Array. Alternativ, wenn Sie .__ lesen. Aus einer Datei gibt File.length die aktuelle Länge der Datei zurück (Obwohl angenommen wird, dass sich die Länge der Datei nicht ändern kann, ist das Lesen von Dateien ___ von Natur aus rassig).

1
yichouangle

Ich habe versucht, die Antwort von @ numan mit einem Fix für das Schreiben von Mülldaten zu bearbeiten, aber die Bearbeitung wurde abgelehnt. Während dieses kurze Stück Code nichts Brillantes ist, kann ich keine bessere Antwort sehen. Folgendes ist für mich am sinnvollsten:

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 muss nicht geschlossen werden. try/finally-Konstrukte wurden zur besseren Lesbarkeit ausgelassen

1
akostadinov

Bei einigen AWS-Transaktionen treten einige Verzögerungen auf, während das S3-Objekt in ByteArray konvertiert wird.

Hinweis: S3-Objekt ist PDF -Dokument (maximale Größe beträgt 3 MB).

Wir verwenden die Option # 1 (org.Apache.commons.io.IOUtils), um das S3-Objekt in ByteArray zu konvertieren. Wir haben festgestellt, dass S3 die inbuild IOUtils-Methode zum Konvertieren des S3-Objekts in ByteArray bereitstellt. Wir bitten Sie, zu bestätigen, wie Sie das S3-Objekt am besten in ByteArray konvertieren, um die Verzögerung zu vermeiden.

Option 1:

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

Option 2:

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

Lassen Sie mich auch wissen, ob wir das s3-Objekt auf andere Weise besser in bytearray konvertieren können

0
Bharathiraja S

Sie können versuchen, Cactoos :

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

Wickeln Sie es in einen DataInputStream ein, wenn dies aus irgendeinem Grund aus dem Tisch ist. Heben Sie ihn einfach mit read an, bis Sie einen -1 oder den gesamten Block erhalten, nach dem Sie gefragt haben.

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;
}
0
Tatarize

Ich benutze das.

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

Der andere Fall, um ein korrektes Byte-Array über einen Stream zu erhalten, nachdem die Anforderung an den Server gesendet und auf die Antwort gewartet wurde.

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

Dies ist meine Copy-Paste-Version:

@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();
}
0
Daniel De León

Hier ist eine optimierte Version, die versucht, das Kopieren von Datenbytes so weit wie möglich zu vermeiden:

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

Sie machen eine zusätzliche Kopie, wenn Sie ByteArrayOutputStream verwenden. Wenn Sie die Länge des Streams kennen, bevor Sie mit dem Lesen beginnen (z. B. ist der InputStream tatsächlich ein FileInputStream, und Sie können file.length () für die Datei aufrufen oder der InputStream ist ein zipfile-Eintrag InputStream und Sie können zipEntry aufrufen. length ()), dann ist es viel besser, direkt in das byte [] -Array zu schreiben - es beansprucht die Hälfte des Speichers und spart Zeit.

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

N.B. In der letzten Zeile wird beschrieben, dass Dateien abgeschnitten werden, während der Stream gelesen wird. Wenn Sie jedoch mit dieser Möglichkeit umgehen müssen, wird die Datei längere während der Stream gelesen wird, während der Stream gelesen wird, der Inhalt des Bytes [] - Arrays nicht verlängert werden, um den neuen Dateiinhalt aufzunehmen, wird das Array einfach auf die alte Länge inputStreamLength gekürzt.

0
Luke Hutchison