15

I have a FileInputStream created using Context.openFileInput(). I now want to convert the file into a byte array.

Unfortunately, I can't determine the size of the byte array required for FileInputStream.read(byte[]). The available() method doesn't work, and I can't create a File to check it's length using the specific pathname, probably because the path is inaccessible to non-root users.

I read about ByteArrayOutputStream, and it seems to dynamically adjust the byte array size to fit, but I can't get how to read from the FileInputStream to write to the ByteArrayOutputStream.

barto90
  • 679
  • 1
  • 9
  • 27
Jeremy Lee
  • 191
  • 1
  • 2
  • 7
  • possible duplicate of [Android - getting from a Uri to an InputStream to a byte array?](http://stackoverflow.com/questions/2436385/android-getting-from-a-uri-to-an-inputstream-to-a-byte-array) – Thilo Mar 17 '11 at 01:43
  • 2
    The `byte[]` you supply to `read(byte[])` isn't intended to be the full size of whatever it is you're trying to read. It's a buffer that can hold the maximum number of bytes you're willing to read at a time, and each call to `read` will put some number of bytes into that buffer and return a number telling you how many bytes it put. – ColinD Mar 17 '11 at 01:52

4 Answers4

45

This should work.

InputStream is = Context.openFileInput(someFileName);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
while ((int bytesRead = is.read(b)) != -1) {
   bos.write(b, 0, bytesRead);
}
byte[] bytes = bos.toByteArray();
Robby Pond
  • 73,164
  • 16
  • 126
  • 119
  • Thanks, I solved with another method though. `while(is .available>0){ bos.write(is.read()) }` – Jeremy Lee Mar 17 '11 at 02:05
  • 5
    @Jeremy: Robby's method is the standard way of doing this in Java. His reads the input up to 1024 bytes at a time... yours reads it 1 byte at a time. I'd advise using his suggestion. – ColinD Mar 17 '11 at 03:04
  • @Mihir May I ask, what do you mean by "this method will work only in rooted device."? Does that mean Robby's method isn't applicable in rooted devices (Android, embedded operating systems, etc.) or devices that are S_OFF or rooted (Specifcally devices mentioned in XDA forums)? Or do you mean that Jeremy's method is suitable for Android? – tom_mai78101 Apr 01 '12 at 09:04
  • Should close the `ByteArrayOutputStream` like `bos.close();` – Muhammad Babar May 30 '14 at 07:53
  • help me with this: http://stackoverflow.com/questions/32996878/showing-gif-image-with-library?noredirect=1#comment53820263_32996878 – Twitter khuong291 Oct 07 '15 at 17:03
  • 1
    @MuhammadBabar as far as I can see the close() method has no effect. – narancs Jul 28 '17 at 21:51
9

This is the easiest way

FileInputStream fis =  openFileInput(fileName);

byte[] buffer =   new byte[(int) fis.getChannel().size()];

fis.read(buffer);
Mohanad Haddadin
  • 569
  • 6
  • 15
  • Please note `openFileInput` method doesn't accept path separators. So instead of `openFileInput`, you can use `fis = new FileInputStream (new File(filename_with_path));` – Atul Dec 29 '16 at 12:49
1

You can pre-allocate the byte array using

int size = context.getFileStreamPath(filename).length();

This way, you will avoid allocating memory chunks every time your ByteArrayOutputStream fills up.

Michael Litvin
  • 3,976
  • 1
  • 34
  • 40
0

For the method to work on any device and aplication you just need to replace:

InputStream is = Context.getContentResolver().openInputStream(yourFileURi);

This way you can encode external files as well.

Shadow The GPT Wizard
  • 66,030
  • 26
  • 140
  • 208
B. TIger
  • 459
  • 3
  • 10
  • 27