Convert InputStream to byte array in Java
Asked Answered
M

34

1009

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

Muddlehead answered 12/8, 2009 at 7:27 Comment(1)
See the reverse: byte[] to InputStream here: stackoverflow.com/questions/2091454/…Karrikarrie
L
1283

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.

Lowering answered 12/8, 2009 at 7:35 Comment(24)
For the want of writing 4 lines of code, you think that importing a 3rd-party dependency is worthwhile?Prosthetics
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 tooLowering
@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.Rego
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 rubbishProsthetics
In addition to Apache commons-io, check out the ByteStreams class from Google Guava. InputStream is; byte[] filedata=ByteStreams.toByteArray(is);Aq
there is "DataInputStream" and its method "readFully" for this usecase - no need of external libraries and strange loops with magic numbers. - see my answer belowBrigittebriley
@JoachimSauer: is Adamski's answer a correct implementation? I wanted to use that one but after reading your comment I'm no more sure.Harrietteharrigan
@bigstone: it looks correct to me, but you don't have to trust me on that: trust the 75 people who upvoted his answer ;-)Rego
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.Pourpoint
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 ?Dictionary
@cytinus, being lazy is to me not having to write/maintain it, not the other way. At school: full implementation, at work: third parties.Tavares
does this answer still hold? Or is there a standard, built-in Java way to do this?Bawdyhouse
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.Ravine
@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;)Dietitian
Pulling in a whole library just to read a stream sums up the problem with Java development as a whole.Adaptation
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.Columbic
@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.Tybalt
Apache Commons is the jQuery of Java.Chitkara
This method is deprecated. can you please update the answer?Gwendagwendolen
@KevinMeredith As of Java 9, there is now has a built-in way to do this. See Holger’s answer.Equilateral
now it is finally in the core library. docs.oracle.com/javase/9/docs/api/java/io/…Until
Commenting to appreciate all master commenters for their knowledge of 3rd party library implementation.Hypsography
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.Karyolysis
I am using this to know the size of a file. Does this function create a copy of the stream (into bytes) in memory? Could I get an out of memory error for large files?Splice
B
495

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();
Baseburner answered 12/8, 2009 at 7:30 Comment(16)
What about the size of newly created byte[]. Why it is 16384? How could I determine exact right size? Thank you very much.Seel
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.Baseburner
@Baseburner Isn't creating array of bytes lot bigger than you expect data would be in the stream, waste the memory ?Tweeze
@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.Baseburner
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.Brutalize
@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).Baseburner
@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".Brutalize
@Craigo: No problem. Arguably I should have named buffer "output" or "sink".Baseburner
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.Breban
Its causes an issue of OutOfMemory when used with large filesCrankpin
@AmitThaper: That isn't surprising; the code reads the entire file into memory (as requested by the OP).Baseburner
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.Apoplectic
@ClayFerguson: Interesting; do you know why 4K is supposed to be optimal in the common case?Baseburner
@Baseburner 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!Apoplectic
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. docs.oracle.com/javase/7/docs/api/java/io/…Twyla
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.Impermeable
T
473

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.

Tybalt answered 7/6, 2016 at 13:50 Comment(6)
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.Impermeable
@Impermeable 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.Tybalt
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.Impermeable
Does this specific InputStream override readAllBytes() or readNBytes?Tybalt
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!Impermeable
Sounds like being worth a question on its own.Tybalt
B
142

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.

Brigittebriley answered 25/1, 2012 at 14:31 Comment(12)
+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.Proudhon
what is imgFile? It's can't be an InputStream, which was supposed to be the input of this methodNickolenicks
@janus it is a "File". this way only works if u know the length of the file or the count of bytes to read.Brigittebriley
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)?Foushee
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.Brigittebriley
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.Goodfornothing
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?!Brigittebriley
If you already know the length of the data to read from the stream, this is no better than InputStream.read.Imogeneimojean
@LoganPickup InputStream.read does not guarantee to return all the bytes you request!Cumquat
@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.Imogeneimojean
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.Cumquat
This should by far be the accepted answer. it is proper since very old java versions; no 3rd party libs.Statutable
I
140

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

byte[] bytes = ByteStreams.toByteArray(inputStream);
Injury answered 4/5, 2014 at 10:37 Comment(0)
M
85

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
    
Microbiology answered 17/11, 2018 at 3:33 Comment(6)
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?Scutt
@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.Microbiology
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.Scutt
@androiddeveloper; Thanks for your information. I didn't know them.Microbiology
the java 8 code version, succesful works for java 1.7 too.Chantay
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...Upwind
H
68

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

Heliozoan answered 18/4, 2017 at 13:59 Comment(1)
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.Abshier
B
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();
}
Basilio answered 25/7, 2013 at 14:33 Comment(4)
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).Pisciform
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?Lifesize
i've taken the liberty to change from 'return null' to 'throw IOException'Anonym
Try-with-resources is not needed here, because ByteArrayOutputStream#close() does nothing. (ByteArrayOutputStream#flush() is not needed and does nothing too.)Ketose
S
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);
Sokotra answered 21/4, 2017 at 17:9 Comment(3)
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) ?Scutt
Sorry, I accidentally downvoted this answer. Could you please edit some characters so that i can undo the click? thanks!Bum
Thanks, @MichaelOuyang. I hope my answer was of help :)Sokotra
W
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

Waxler answered 12/8, 2009 at 8:14 Comment(0)
L
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;
}
Lifeordeath answered 17/9, 2014 at 14:4 Comment(3)
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)Ketose
@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.Lifeordeath
@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.Barrow
C
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();
Califate answered 1/11, 2013 at 2:25 Comment(0)
S
10
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();
Southwesterly answered 7/6, 2010 at 8:59 Comment(2)
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).Belita
@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.Tybalt
H
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;
}
Headstream answered 8/6, 2011 at 8:30 Comment(5)
Depends on knowing size upfront.Josefjosefa
Of course, but they should know the size: "I want to read an image"Headstream
if you know the size, then java provides the code for you. see my answer or google for "DataInputStream" and it's readFully method.Brigittebriley
You should add is.close() if offset < bytes.length or the InputStream will not be closed if that exception is thrown.Landbert
Then better, you should use try-with-resourcesHeadstream
O
5

Java 9 will give you finally a nice method:

InputStream in = ...;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
in.transferTo( bos );
byte[] bytes = bos.toByteArray();
Oliveolivegreen answered 28/2, 2017 at 20:55 Comment(2)
What's the difference between this and InputStram.readAllBytes() that is one-liner?Kitchenmaid
A lot of array resizing in ByteArrayOutputStream for sure, followed by a full copy of the data.Belita
C
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

Cut answered 4/6, 2018 at 12:38 Comment(0)
C
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();
}
Cantwell answered 3/6, 2015 at 11:27 Comment(2)
You should use try-with-resources.Azotobacter
Your tidying up at the end needs to be done in a finally block in case of errors, otherwise this could cause a memory leak.Chug
H
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

Haden answered 20/3, 2013 at 7:22 Comment(0)
D
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).

Demarcate answered 7/9, 2015 at 16:0 Comment(0)
T
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;
}
Tachometer answered 3/12, 2016 at 8:22 Comment(0)
K
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.

Khalil answered 3/5, 2017 at 19:56 Comment(3)
That is for String. OP is asking for byte[].Pyroelectric
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.Mislike
Seems like this is good answer, but text-oriented. Buyer beware.Thracian
C
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;
   }
}
Chanukah answered 5/4, 2015 at 2:32 Comment(0)
S
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);
Synecology answered 14/7, 2015 at 8:3 Comment(0)
K
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.

Ketose answered 30/7, 2015 at 11:0 Comment(0)
F
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;
    }
Fogy answered 26/8, 2015 at 9:56 Comment(1)
Why convert to String and then to byte[] (which might mess with binary data)? ByteArrayOutputStream has .toByteArray(): docs.oracle.com/javase/7/docs/api/java/io/…Spancake
V
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();
        }
    }
Valedictorian answered 13/1, 2016 at 5:5 Comment(1)
Add some explanation with answer for how this answer help OP in fixing current issueErlin
A
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();
}
Arc answered 11/3, 2016 at 4:10 Comment(1)
While this code snippet may solve the question, including an explanation 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.Emanuele
S
0

Java 7 and later:

import sun.misc.IOUtils;
...
InputStream in = ...;
byte[] buf = IOUtils.readFully(in, -1, false);
Selfpreservation answered 20/3, 2016 at 7:56 Comment(1)
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.Tybalt
P
0

You can try Cactoos:

byte[] array = new BytesOf(stream).bytes();
Preciousprecipice answered 27/8, 2017 at 12:58 Comment(0)
S
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://mcmap.net/q/17249/-get-file-path-from-uri
        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
    }
Scutt answered 16/5, 2020 at 11:32 Comment(0)
A
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.

Antwanantwerp answered 30/6, 2020 at 21:41 Comment(0)
L
0

For Android developers dealing with the inter-op between Java and Kotlin:

byte[] myByteArray = ByteStreamsKt.readBytes(fileInputStream);
Lester answered 16/10, 2023 at 17:51 Comment(0)
F
-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();
}
Felicitasfelicitate answered 1/6, 2011 at 15:22 Comment(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.Haden
C
-4

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();
Cruzcruzado answered 12/8, 2009 at 7:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.