999

How do I read an entire InputStream into a byte array?

Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
JGC
  • 12,737
  • 9
  • 35
  • 57

34 Answers34

1274

You can use Apache Commons IO to handle this and similar tasks.

The IOUtils type has a static method to read an InputStream and return a byte[].

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

Internally this creates a ByteArrayOutputStream and copies the bytes to the output, then calls toByteArray(). It handles large files by copying the bytes in blocks of 4KiB.

Lektonic
  • 200
  • 10
Rich Seller
  • 83,208
  • 23
  • 172
  • 177
  • 221
    For the want of writing 4 lines of code, you think that importing a 3rd-party dependency is worthwhile? – oxbow_lakes Aug 12 '09 at 10:24
  • 240
    If there is a library that handles the requirement, and deals with processing for large files, and is well tested, surely the question is why would I write it myself? The jar is only 107KB and if you have need for one method from it, you are likely to use others too – Rich Seller Aug 12 '09 at 10:46
  • 263
    @oxbow_lakes: considering the staggering amount of **wrong** implementations of this feature I've seen in my developer life, I feel that **yes** it's *very* much worth the external dependency to get it right. – Joachim Sauer Jun 08 '10 at 12:45
  • 20
    Why not go and have a look at Apache commons stuff like `FastArrayList` or their soft & weak reference Maps and come back to tell me how "well-tested" this library is. It's a pile of rubbish – oxbow_lakes Jun 09 '10 at 07:09
  • 92
    In addition to Apache commons-io, check out the [ByteStreams](http://docs.guava-libraries.googlecode.com/git-history/v10.0.1/javadoc/com/google/common/io/ByteStreams.html) class from [Google Guava](http://code.google.com/p/guava-libraries/). `InputStream is;` `byte[] filedata=ByteStreams.toByteArray(is);` – michaelok Dec 29 '11 at 20:35
  • 2
    there is "DataInputStream" and its method "readFully" for this usecase - no need of external libraries and strange loops with magic numbers. - see my answer below – dermoritz Jan 25 '12 at 14:24
  • 1
    @JoachimSauer: is [Adamski's answer](http://stackoverflow.com/a/1264737/503900) a correct implementation? I wanted to use that one but after reading your comment I'm no more sure. – bigstones Oct 02 '12 at 21:42
  • @bigstone: it looks correct to me, but you don't have to trust me on that: trust the 75 people who upvoted his answer ;-) – Joachim Sauer Oct 03 '12 at 04:56
  • 2
    The only reason not to use a time-tested 3rd-party dependency is because you are lazy and/or not using best practices. Use a dependency management tool like Maven and then yea, it is worthwhile. – cytinus Apr 03 '13 at 17:56
  • 5
    in response to `go and have a look at Apache commons stuff like FastArrayList or their soft & weak reference Maps and come back to tell me how "well-tested" this library is` ... that's like saying "taste those brussel sprouts and tell me how good these tomatoes are". If I add these tomatoes to my dish, taste test it, like it and everyone else apparently likes it too, then what do I care of the brussel sprouts from the same grocer are ka-ka ? – Michael M Sep 25 '13 at 18:47
  • 2
    @cytinus, being lazy is to me not having to write/maintain it, not the other way. At school: full implementation, at work: third parties. – Aritz Feb 26 '14 at 15:59
  • does this answer still hold? Or is there a standard, built-in Java way to do this? – Kevin Meredith Jan 20 '15 at 19:58
  • 2
    `IOUtils.toByteArray(InputStream)` only copies in blocks of 4KB, not 4MB. In IOUtils.java the block size is defined as `private static final int DEFAULT_BUFFER_SIZE = 1024 * 4`. – Christian d'Heureuse Apr 05 '15 at 01:52
  • 2
    @JoachimSauer You're exactly to the point on using third party libraries for this. I just finished spending two whole days just to figure out someone has badly implemented a byte array conversion. Using IOUtils I could get rid of the problem. Voted up the answer and your comment;) – dimuthu May 07 '15 at 10:03
  • 4
    Pulling in a whole library just to read a stream sums up the problem with Java development as a whole. – Glenn Maynard Jul 06 '15 at 21:03
  • may be one should justify the decision to have dependency on third party library based on 1. Is it worth to re-invent the wheel 2. Is my JVM heap/permgen too small to have big impact of this dependency. – Nayn Mar 09 '16 at 03:41
  • 4
    @Nayn: the problem with using a 3rd party solution is first, the assumption that 3rd party developers are smarter than you, just because they are writing a 3rd party library or that the 3rd party library’s code is “well tested”, just because it resides in a 3rd party library. And well, more than often, it’s not one 3rd party library dependency, but a dozen, because these 3rd party libraries are written by developers who also don’t care about minimizing 3rd party library dependencies. There is a tendency of Java developers to know more about 3rd party libraries than about the standard API. – Holger Jun 07 '16 at 13:26
  • 1
    Apache Commons is the jQuery of Java. – Adam Arold Dec 29 '16 at 15:00
  • 2
    This method is deprecated. can you please update the answer? – No Idea For Name Aug 01 '17 at 09:36
  • 2
    @KevinMeredith As of Java 9, there is now has a built-in way to do this. See [Holger’s answer](https://stackoverflow.com/a/37681322/1441122). – Stuart Marks Dec 27 '18 at 07:25
  • 1
    now it is finally in the core library. https://docs.oracle.com/javase/9/docs/api/java/io/InputStream.html#readAllBytes-- – user9999 Aug 05 '20 at 14:43
  • Commenting to appreciate all master commenters for their knowledge of 3rd party library implementation. – ScanQR Sep 06 '21 at 12:06
  • This is resolved my issue. On trying to convert a .zpl stream, some of the characters where getting messed up when handling this on my own. The library works well. – Tinashe Chinyanga Oct 20 '21 at 20:32
493

You need to read each byte from your InputStream and write it to a ByteArrayOutputStream.

You can then retrieve the underlying byte array by calling 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();
Arsen Khachaturyan
  • 7,904
  • 4
  • 42
  • 42
Adamski
  • 54,009
  • 15
  • 113
  • 152
  • 23
    What about the size of newly created byte[]. Why it is 16384? How could I determine exact right size? Thank you very much. – Ondrej Bozek Apr 03 '12 at 09:45
  • 6
    16384 is a fairly arbitrary choice although I tend to favour powers of 2 to increase the chance of the array aligning with word boundaries. pihentagy's answer shows how you can avoid using an intermediate buffer, but rather allocate an array of the correct size. Unless you're dealing with large files I personally prefer the code above, which is more elegant and can be used for InputStreams where the number of bytes to read is not known in advance. – Adamski Apr 03 '12 at 11:33
  • @Adamski Isn't creating array of bytes lot bigger than you expect data would be in the stream, waste the memory ? – Paweł Brewczynski Jun 29 '13 at 16:38
  • @bluesm: Yes that's correct. However, in my example the byte array is only 16Kb and so tiny by today's standards. Also, of course this memory will be freed again afterwards. – Adamski Jul 04 '13 at 07:36
  • When you're writing to your buffer, your start offset is always 0, so if the data is larger than 16384, then it will write over itself. – Craigo Dec 11 '15 at 00:53
  • @Craigo: The offset: 0 applies to the data[] array being written from not the location in the output buffer (which is an OutputStream and hence does not support random access; all writes are append-only). – Adamski Dec 14 '15 at 09:23
  • @Adamski: Sorry, you are correct. I got confused because I thought the result byte array was the "data", but, rereading the code, it is actually the contents of "buffer". – Craigo Dec 16 '15 at 00:10
  • @Craigo: No problem. Arguably I should have named buffer "output" or "sink". – Adamski Dec 16 '15 at 10:20
  • I have searched for over two days but couldn't find anywhere a clear solution to read bytes from an InputStream when using a TCP socket on my client. Yours is the only one which helped me. Thanks. – zeeshan Sep 09 '16 at 15:54
  • Its causes an issue of OutOfMemory when used with large files – Amit Thaper Dec 08 '16 at 14:05
  • @AmitThaper: That isn't surprising; the code reads the entire file into memory (as requested by the OP). – Adamski Dec 08 '16 at 17:12
  • I always use Apache Commons IOUtils mentioned in the higher rated answer, but as for the 16K buffer size, most streaming is done still today using 4K buffer size, because that ends up being optimal. Allocating a larger buffer will not get better performance but will just eat up memory unnecessarily. 4K is ideal. –  Mar 24 '17 at 00:17
  • @ClayFerguson: Interesting; do you know why 4K is supposed to be optimal in the common case? – Adamski Mar 29 '17 at 12:54
  • 6
    @Adamski A lot of infrastructure hardware, web-servers, and OS-layer components are using 4K buffers to move data, so that's the reason for the exact number, but the main point is that you get such little performance boost by going over 4K that it's generally considered wasteful of memory. I'm assuming this is *still* true, because it's decade old knowledge I had! –  Mar 30 '17 at 14:14
  • We can use inputStream.available() to find out the number of bytes that the array occupies, then use that size to instantiate the byte array. https://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html#available() – LCZ Oct 20 '20 at 06:36
  • I'ts the Better solution from all answers: Vanilla java, not much lines, uses a buffer and adapt to every inputStream. I will add it to my common utils. – pdem Dec 17 '21 at 14:56
459

Finally, after twenty years, there’s a simple solution without the need for a 3rd party library, thanks to Java 9:

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

Note also the convenience methods readNBytes(byte[] b, int off, int len) and transferTo(OutputStream) addressing recurring needs.

Holger
  • 285,553
  • 42
  • 434
  • 765
  • 2
    Java documentation "Note that this method is intended for simple cases where it is convenient to read all bytes into a byte array. It is not intended for reading input streams with large amounts of data." and in fact it was limited to 8192 from my test (undocumented) Use it for test, but not in production. – pdem Dec 17 '21 at 14:52
  • 4
    @pdem there is no such limit. I just verified it by reading a 2GiB file into memory. It works, as long as an appropriately large array can be allocated. If you get different results, it’s a problem of your test setup. The point that you *should not* read such large files into memory, but prefer processing them while reading, is an entirely different thing. It obviously applies to all solutions presented in the Q&A, as they all are about reading an entire file into memory. – Holger Dec 17 '21 at 15:04
  • Well you are very reactive, I've tested 2 jdk (11 17) and it works with a big byteInputstream as you said, so i Guess there is a problem with may api with is a javamail: I get files from a mimemessage content. What is strange is that the bug related to the javamail, doesn't appear with a classical manual read. – pdem Dec 17 '21 at 15:21
  • 1
    Does this specific `InputStream` override `readAllBytes()` or `readNBytes`? – Holger Dec 17 '21 at 15:28
  • Yes and no, it's a BASE64DecoderStream which delegate to a SharedByteArrayInputStream which extends ByteArrayInputStream which override readAllBytes. I get lost in the multiple code delegation. Whatever I could isolate the bug of BASE64DecoderStream in a unit test. I understand that the bug is not from the JDK, still, I need a workaround here because of the implementation of BASE64DecoderStream. Thanks for your time! – pdem Dec 17 '21 at 16:38
  • 2
    Sounds like being worth a question on its own. – Holger Dec 20 '21 at 08:34
141

Use vanilla Java's DataInputStream and its readFully Method (exists since at least Java 1.4):

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

There are some other flavors of this method, but I use this all the time for this use case.

Gerold Broser
  • 14,080
  • 5
  • 48
  • 107
dermoritz
  • 12,519
  • 25
  • 97
  • 185
  • 51
    +1 for using the standard libraries instead of a 3rd party dependency. Unfortunately it doesn't work for me because I don't know the length of the stream upfront. – Andrew Spencer Jun 07 '12 at 09:28
  • 2
    what is imgFile? It's can't be an InputStream, which was supposed to be the input of this method – Janus Troelsen Jul 20 '13 at 09:43
  • 4
    @janus it is a "File". this way only works if u know the length of the file or the count of bytes to read. – dermoritz Jul 28 '13 at 09:49
  • How did you figure this out? Can you explain how you came up with this code, so I can learn how to do the same (and avoid asking questions each time)? – CodyBugstein May 24 '14 at 23:59
  • As mentioned in my answer, i found this via google, but not on first page. And because i wanted to find this solution faster i added the answer here. – dermoritz May 26 '14 at 13:06
  • 6
    Interesting thing, but you must know the exact length of the (part of the) stream to read. Moreover, the class `DataInputStream` is primary used to read primary types (Longs, Shorts, Chars...) from a stream, so we can see this usage as a misuse of the class. – Olivier Faucheux Apr 08 '15 at 11:51
  • is there a source for "primary used to read primary types (Longs, Shorts, Chars...) from a stream". But on the other hand i think a usage out of primary use is not misuse?! – dermoritz Apr 08 '15 at 13:19
  • 20
    If you already know the length of the data to read from the stream, this is no better than `InputStream.read`. – Logan Pickup Oct 12 '16 at 03:57
  • 4
    @LoganPickup InputStream.read does not guarantee to return all the bytes you request! – Ray Hulha Oct 15 '18 at 03:32
  • 1
    @RayHulha Neither does `readFully` - the difference is in how they handle the stream ending before the number of bytes requested has been read. `read` quits early and returns the number of bytes read, `readFully` throws an exception. – Logan Pickup Oct 15 '18 at 07:18
  • 3
    `readFully` loops internally until it has the needed bytes. This is much more convenient than using `read` where you have to write the loop yourself. So I would argue it is better. I just had this exact case happen to me with a GZIPInputStream where a read call would return with just a fraction of the needed bytes and readFully read them all. And in both cases I knew the length of the data to read from the stream. – Ray Hulha Oct 16 '18 at 03:56
  • This should by far be the accepted answer. it is proper since very old java versions; no 3rd party libs. – Ordiel Feb 16 '19 at 13:50
138

If you happen to use Google Guava, it'll be as simple as using ByteStreams:

byte[] bytes = ByteStreams.toByteArray(inputStream);
Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
Bertie
  • 17,277
  • 45
  • 129
  • 182
81

Safe solution (close streams correctly):

  • Java 9 and newer:

     final byte[] bytes;
     try (inputStream) {
         bytes = inputStream.readAllBytes();
     }
    

  • Java 8 and older:

     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 (when Java 9+ isn't accessible):

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

    To avoid nested use see here.


  • Scala (when Java 9+ isn't accessible) (By @Joan. Thx):

    def readAllBytes(inputStream: InputStream): Array[Byte] =
      Stream.continually(inputStream.read).takeWhile(_ != -1).map(_.toByte).toArray
    
Mir-Ismaili
  • 13,974
  • 8
  • 82
  • 100
  • Doesn't it mean that at some point you'd have double the memory used, because you have both the buffer and the byte array? Isn't there a way to send the bytes directly to the output byte array? – android developer May 06 '20 at 23:12
  • @androiddeveloper; I'm sorry. I don't know the answer! But I don't think so. I think this way (using buffer) is an optimized way. – Mir-Ismaili May 07 '20 at 21:07
  • I've checked and it does, but it seems that it's the only solution you can choose when you don't know the size. If you already know the size, you can directly create the byte-array with the given size and fill it. So, you use a function that will get a parameter of the byte size, and if it's valid, use it to directly create and fill the byte array, without creating any other large object. – android developer May 08 '20 at 06:19
  • @androiddeveloper; Thanks for your information. I didn't know them. – Mir-Ismaili May 09 '20 at 20:59
  • 2
    the java 8 code version, succesful works for java 1.7 too. – LKF Oct 25 '22 at 03:58
  • Why are you closing the `ByteArrayOutputStream`? This is not proper, and implies to people reading the code that it needs to be closed, though closing a `ByteArrayOutputStream` does nothing. In fact, that entire `try` where the `ByteArrayOutputStream` is declared should be rewritten. There's no need for a `try` block there... – Kröw Jul 26 '23 at 04:07
67

As always, also Spring framework (spring-core since 3.2.2) has something for you: StreamUtils.copyToByteArray()

Arne Burmeister
  • 20,046
  • 8
  • 53
  • 94
  • 2
    Like most others, I wanted to avoid using a 3rd party library for something so simple, but Java 9 is not an option at the moment...luckily, I was already using Spring. – scottysseus Oct 15 '18 at 21:54
48
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();
}
Ivan Gammel
  • 652
  • 7
  • 17
oliverkn
  • 743
  • 9
  • 14
  • 2
    It is an example and as such, brevity is the order of the day. Also returning null here would be the proper choice in some cases (although in a production environment you would also have proper exception handling and documentation). –  Mar 06 '14 at 17:59
  • 13
    I understand brevity in an example, but why not just make the example method throw IOException rather than swallowing it and returning a meaningless value? – pendor May 18 '14 at 23:22
  • 5
    i've taken the liberty to change from 'return null' to 'throw IOException' – kritzikratzi Apr 30 '15 at 14:13
  • 4
    Try-with-resources is not needed here, because ByteArrayOutputStream#close() does nothing. (ByteArrayOutputStream#flush() is not needed and does nothing too.) – Luke Hutchison Oct 05 '17 at 05:11
21

In-case someone is still looking for a solution without dependency and If you have a file.

DataInputStream

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

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

RandomAccessFile

 RandomAccessFile raf = new RandomAccessFile(file, "r");
 byte[] data = new byte[(int) raf.length()];
 raf.readFully(data);
harsh_v
  • 3,193
  • 3
  • 34
  • 53
  • Say, what if the byte array is too large which could cause OOM for the heap? Is there a similar solution that will use JNI to store the bytes, and later we'd be able to use inputStream from the data stored there (sort of temporary cache) ? – android developer May 06 '20 at 23:15
  • Sorry, I accidentally downvoted this answer. Could you please edit some characters so that i can undo the click? thanks! – Michael Ouyang Sep 26 '20 at 07:28
  • Thanks, @MichaelOuyang. I hope my answer was of help :) – harsh_v Sep 26 '20 at 16:42
19

Do you really need the image as a byte[]? What exactly do you expect in the byte[] - the complete content of an image file, encoded in whatever format the image file is in, or RGB pixel values?

Other answers here show you how to read a file into a byte[]. Your byte[] will contain the exact contents of the file, and you'd need to decode that to do anything with the image data.

Java's standard API for reading (and writing) images is the ImageIO API, which you can find in the package javax.imageio. You can read in an image from a file with just a single line of code:

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

This will give you a BufferedImage, not a byte[]. To get at the image data, you can call getRaster() on the BufferedImage. This will give you a Raster object, which has methods to access the pixel data (it has several getPixel() / getPixels() methods).

Lookup the API documentation for javax.imageio.ImageIO, java.awt.image.BufferedImage, java.awt.image.Raster etc.

ImageIO supports a number of image formats by default: JPEG, PNG, BMP, WBMP and GIF. It's possible to add support for more formats (you'd need a plug-in that implements the ImageIO service provider interface).

See also the following tutorial: Working with Images

Jesper
  • 202,709
  • 46
  • 318
  • 350
15

If you don't want to use the Apache commons-io library, this snippet is taken from the sun.misc.IOUtils class. It's nearly twice as fast as the common implementation using 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;
}
Kristian Kraljic
  • 826
  • 12
  • 11
  • This is a bit of a weird solution, *length* is an upper bound on the length of the array. If you know the length, all you need is: byte[] output = new byte[length]; is.read(output); (but see my answer) – Luke Hutchison Jul 30 '15 at 11:16
  • @luke-hutchison as I said, this is the solution of sun.misc.IOUtils. In the most common cases you don't know the size of an InputStream upfront, so if (length == -1) length = Integer.MAX_VALUE; applies. This solution works, even if the given length is larger than the length of the InputStream. – Kristian Kraljic Jul 31 '15 at 12:57
  • @LukeHutchison If you know the length you can handle it with a few lines. If you look at each answer, everyone is complaining that the length is not known. Finally an answer which is standard, can be used with Java 7 Android, and doesn't require any external library. – Csaba Toth Feb 27 '17 at 07:00
12
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();
YulCheney
  • 2,877
  • 2
  • 18
  • 14
9
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();
Aturio
  • 131
  • 1
  • 1
  • However, usually the OS already buffers enough for this not be be a huge worry for smaller files. It's not like the hard disk head will read each byte separately (a hard disk is a turning glass plate with magnetic coded information on it, a bit like that weird icon we use for saving data :P). – Maarten Bodewes Nov 22 '16 at 15:33
  • 7
    @Maarten Bodewes: most devices have a kind of block transfer, so not every read() will cause an actual device access, indeed, but having an OS-call per byte is already sufficient to kill the performance. While wrapping the `InputStream` in a `BufferedInputStream` before that code would reduce the OS-calls and mitigate the performance drawbacks significantly, that code will still do unnecessary manual copying work from one buffer to another. – Holger Dec 14 '16 at 09:54
9

@Adamski: You can avoid buffer entirely.

Code copied from http://www.exampledepot.com/egs/java.io/File2ByteArray.html (Yes, it is very verbose, but needs half the size of memory as the other solution.)

// 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;
}
pihentagy
  • 5,975
  • 9
  • 39
  • 58
5

Java 9 will give you finally a nice method:

InputStream in = ...;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
in.transferTo( bos );
byte[] bytes = bos.toByteArray();
Christian Ullenboom
  • 1,388
  • 3
  • 24
  • 20
4

We are seeing some delay for few AWS transaction, while converting S3 object to ByteArray.

Note: S3 Object is PDF document (max size is 3 mb).

We are using the option #1 (org.apache.commons.io.IOUtils) to convert the S3 object to ByteArray. We have noticed S3 provide the inbuild IOUtils method to convert the S3 object to ByteArray, we are request you to confirm what is the best way to convert the S3 object to ByteArray to avoid the delay.

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

Also let me know if we have any other better way to convert the s3 object to bytearray

Bharathiraja S
  • 679
  • 4
  • 12
  • 26
2

I know it's too late but here I think is cleaner solution that's more readable...

/**
 * 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();
}
Simple-Solution
  • 4,209
  • 12
  • 47
  • 66
1

I tried to edit @numan's answer with a fix for writing garbage data but edit was rejected. While this short piece of code is nothing brilliant I can't see any other better answer. Here's what makes most sense to 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 need not be closed. try/finally constructs omitted for readability

akostadinov
  • 17,364
  • 6
  • 77
  • 85
1

See the InputStream.available() documentation:

It is particularly important to realize that you must not use this method to size a container and assume that you can read the entirety of the stream without needing to resize the container. Such callers should probably write everything they read to a ByteArrayOutputStream and convert that to a byte array. Alternatively, if you're reading from a file, File.length returns the current length of the file (though assuming the file's length can't change may be incorrect, reading a file is inherently racy).

Dominik Sandjaja
  • 6,326
  • 6
  • 52
  • 77
1

Wrap it in a DataInputStream if that is off the table for some reason, just use read to hammer on it until it gives you a -1 or the entire block you asked for.

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;
}
Tatarize
  • 10,238
  • 4
  • 58
  • 64
1

Java 8 way (thanks to BufferedReader and 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>);
    }
}

Note that this solution wipes carriage return ('\r') and can be inappropriate.

yegor256
  • 102,010
  • 123
  • 446
  • 597
Ilya Bystrov
  • 2,902
  • 2
  • 14
  • 21
  • 4
    That is for `String`. OP is asking for `byte[]`. – FrozenFire May 06 '17 at 07:39
  • It's not just `\r` that could be a problem. This method converts the bytes to characters and back again (using the default character set for InputStreamReader). Any bytes which aren't valid in the default character encoding (say, -1 for UTF-8 on Linux) will be corrupted, potentially even changing the number of bytes. – seanf Jun 15 '18 at 14:36
  • Seems like this is good answer, but text-oriented. Buyer beware. – Wheezil Aug 21 '18 at 00:09
0

Here is an optimized version, that tries to avoid copying data bytes as much as possible:

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;
   }
}
Christian d'Heureuse
  • 5,090
  • 1
  • 32
  • 28
0

The other case to get correct byte array via stream, after send request to server and waiting for the response.

/**
         * 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);
Huy Tower
  • 7,769
  • 16
  • 61
  • 86
0

You're doing an extra copy if you use ByteArrayOutputStream. If you know the length of the stream before you start reading it (e.g. the InputStream is actually a FileInputStream, and you can call file.length() on the file, or the InputStream is a zipfile entry InputStream, and you can call zipEntry.length()), then it's far better to write directly into the byte[] array -- it uses half the memory, and saves time.

// 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. the last line above deals with files getting truncated while the stream is being read, if you need to handle that possibility, but if the file gets longer while the stream is being read, the contents in the byte[] array will not be lengthened to include the new file content, the array will simply be truncated to the old length inputStreamLength.

Luke Hutchison
  • 8,186
  • 2
  • 45
  • 40
0

This works for 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;
    }
tk_
  • 16,415
  • 8
  • 80
  • 90
  • Why convert to `String` and then to `byte[]` (which might mess with binary data)? `ByteArrayOutputStream` has `.toByteArray()`: https://docs.oracle.com/javase/7/docs/api/java/io/ByteArrayOutputStream.html#toByteArray() – Thomas Perl Oct 18 '17 at 09:51
0

I use this.

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();
        }
    }
cchcc
  • 335
  • 2
  • 6
0

This is my 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();
}
Daniel De León
  • 13,196
  • 5
  • 87
  • 72
  • 2
    While this code snippet may solve the question, [including an explanation](http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. – Ferrybig Apr 14 '16 at 12:35
0

Java 7 and later:

import sun.misc.IOUtils;
...
InputStream in = ...;
byte[] buf = IOUtils.readFully(in, -1, false);
Anthony
  • 12,407
  • 12
  • 64
  • 88
  • 22
    `sun.misc.IOUtils` is not “Java 7”. It’s a proprietary, implementation specific class that may not be present in other JRE implementations and can disappear without any warning in one of the next releases. – Holger Jun 07 '16 at 13:17
0

You can try Cactoos:

byte[] array = new BytesOf(stream).bytes();
yegor256
  • 102,010
  • 123
  • 446
  • 597
0

Solution in Kotlin (will work in Java too, of course), which includes both cases of when you know the size or not:

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

If you know the size, it saves you on having double the memory used compared to the other solutions (in a brief moment, but still could be useful). That's because you have to read the entire stream to the end, and then convert it to a byte array (similar to ArrayList which you convert to just an array).

So, if you are on Android, for example, and you got some Uri to handle, you can try to get the size using this:

    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
    }
android developer
  • 114,585
  • 152
  • 739
  • 1,270
0

You can use cactoos library with provides reusable object-oriented Java components. OOP is emphasized by this library, so no static methods, NULLs, and so on, only real objects and their contracts (interfaces). A simple operation like reading InputStream, can be performed like that

final InputStream input = ...;
final Bytes bytes = new BytesOf(input);
final byte[] array = bytes.asBytes();
Assert.assertArrayEquals(
    array,
    new byte[]{65, 66, 67}
);

Having a dedicated type Bytes for working with data structure byte[] enables us to use OOP tactics for solving tasks at hand. Something that a procedural "utility" method will forbid us to do. For example, you need to enconde bytes you've read from this InputStream to Base64. In this case you will use Decorator pattern and wrap Bytes object within implementation for Base64. cactoos already provides such implementation:

final Bytes encoded = new BytesBase64(
    new BytesOf(
        new InputStreamOf("XYZ")
    )
);
Assert.assertEquals(new TextOf(encoded).asString(), "WFla");

You can decode them in the same manner, by using Decorator pattern

final Bytes decoded = new Base64Bytes(
    new BytesBase64(
        new BytesOf(
            new InputStreamOf("XYZ")
        )
    )
);
Assert.assertEquals(new TextOf(decoded).asString(), "XYZ");

Whatever your task is you will be able to create own implementation of Bytes to solve it.

andreoss
  • 1,570
  • 1
  • 10
  • 25
0

You can use Cactoos (I'm one of its developers):

import org.cactoos.bytes.BytesOf;
byte[] array = new BytesOf(stream).asBytes();

You can also convert a stream to a String:

import org.cactoos.text.TextOf;
String txt = new TextOf(stream).asString();

Both asBytes() and asString() methods throw checked Exception. If you don't want to catch it, use Unchecked* decorators, for example:

import org.cactoos.bytes.BytesOf;
import org.cactoos.bytes.UncheckedBytes;
byte[] array = new UncheckedBytes(new BytesOf(stream)).asBytes();
yegor256
  • 102,010
  • 123
  • 446
  • 597
-1
/*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();
}
Andrei Sfat
  • 8,440
  • 5
  • 49
  • 69
Madhu
  • 1
  • 1
  • Closing and flushing bos is a waste of keyboard clicks. Closing the input stream is more likely to help. Reading one byte at a time is inefficient. See numan's answer. – akostadinov Mar 19 '13 at 17:14
-3

Below Codes

public static byte[] serializeObj(Object obj) throws IOException {
  ByteArrayOutputStream baOStream = new ByteArrayOutputStream();
  ObjectOutputStream objOStream = new ObjectOutputStream(baOStream);

  objOStream.writeObject(obj); 
  objOStream.flush();
  objOStream.close();
  return baOStream.toByteArray(); 
} 

OR

BufferedImage img = ...
ByteArrayOutputStream baos = new ByteArrayOutputStream(1000);
ImageIO.write(img, "jpeg", baos);
baos.flush();
byte[] result = baos.toByteArray();
baos.close();
firstthumb
  • 4,627
  • 6
  • 35
  • 45