35
FileInputStream in = new FileInputStream(myFile);
ByteArrayOutputStream out = new ByteArrayOutputStream();

Question: How can I read everything from in into out in a way which is not a hand-crafted loop with my own byte buffer?

Harry Joy
  • 58,650
  • 30
  • 162
  • 207
Konrad Garus
  • 53,145
  • 43
  • 157
  • 230

7 Answers7

43

Java 9 (and later) answer (docs):

in.transferTo(out);

Seems they finally realized that this functionality is so commonly needed that it’d better be built in. The method returns the number of bytes copied in case you need to know.

Nayuki
  • 17,911
  • 6
  • 53
  • 80
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
35

Write one method to do this, and call it from everywhere which needs the functionality. Guava already has code for this, in ByteStreams.copy. I'm sure just about any other library with "general" IO functionality has it too, but Guava's my first "go-to" library where possible. It rocks :)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • The `ByteStreams` is annoted as `@Beta` is that not an issue? – gabuzo Feb 07 '11 at 10:18
  • 2
    @gabuzo: That depends on just how risk averse you are. I suspect that it's very unlikely that that method call will change, and I'm sure the implementation is fine. – Jon Skeet Feb 07 '11 at 10:27
  • 1
    Even if it changes or disappears, you only risk to have to fix it in case you upgrade. The method is simple and the source code available (even as subversion repo). – maaartinus Feb 08 '11 at 00:08
20

In Apache Commons / IO, you can do it using IOUtils.copy(in, out):

InputStream in = new FileInputStream(myFile);
OutputStream out = new ByteArrayOutputStream();
IOUtils.copy(in, out);

But I agree with Jon Skeet, I'd rather use Guava's ByteStreams.copy(in, out)

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
13

So what Guava's ByteStreams.copy(in, out) does:

  private static final int BUF_SIZE = 0x1000; // 4K

  public static long copy(InputStream from, OutputStream to)
      throws IOException {
    checkNotNull(from);
    checkNotNull(to);
    byte[] buf = new byte[BUF_SIZE];
    long total = 0;
    while (true) {
      int r = from.read(buf);
      if (r == -1) {
        break;
      }
      to.write(buf, 0, r);
      total += r;
    }
    return total;
  }
user58635
  • 131
  • 1
  • 2
7

In my project I used this method:

private static void copyData(InputStream in, OutputStream out) throws Exception {
    byte[] buffer = new byte[8 * 1024];
    int len;
    while ((len = in.read(buffer)) > 0) {
        out.write(buffer, 0, len);
    }
}
Sergey Nemchinov
  • 1,348
  • 15
  • 21
2

Alternatively to Guava one could use Apache Commons IO (old), and Apache Commons IOUtils (new as advised in the comment).

01es
  • 5,362
  • 1
  • 31
  • 40
0

I'd use the loop, instead of importing new classes, or adding libraries to my project. The library function is probably also implemented with a loop. But that's just my personal taste.

However, my question to you: what are you trying to do? Think of the "big picture", if you want to put the entire contents of a file into a byte array, why not just do that? The size of the arrray is file.length(), and you don't need it to dynamically grow, hidden behind a ByteArrayOutputStream (unless your file is shared, and its contents can change while you read).

Another alternative: could you use a FileChannel and a ByteBuffer (java.nio)?

G B
  • 2,951
  • 2
  • 28
  • 50