75

Possible Duplicate:
File to byte[] in Java

I want to read data from file and unmarshal it to Parcel. In documentation it is not clear, that FileInputStream has method to read all its content. To implement this, I do folowing:

FileInputStream filein = context.openFileInput(FILENAME);


int read = 0;
int offset = 0;
int chunk_size = 1024;
int total_size = 0;

ArrayList<byte[]> chunks = new ArrayList<byte[]>();
chunks.add(new byte[chunk_size]);
//first I read data from file chunk by chunk
while ( (read = filein.read(chunks.get(chunks.size()-1), offset, buffer_size)) != -1) {
    total_size+=read;
    if (read == buffer_size) {
         chunks.add(new byte[buffer_size]);
    }
}
int index = 0;

// then I create big buffer        
byte[] rawdata = new byte[total_size];

// then I copy data from every chunk in this buffer
for (byte [] chunk: chunks) {
    for (byte bt : chunk) {
         index += 0;
         rawdata[index] = bt;
         if (index >= total_size) break;
    }
    if (index>= total_size) break;
}

// and clear chunks array
chunks.clear();

// finally I can unmarshall this data to Parcel
Parcel parcel = Parcel.obtain();
parcel.unmarshall(rawdata,0,rawdata.length);

I think this code looks ugly, and my question is: How to do read data from file into byte[] beautifully? :)

Community
  • 1
  • 1
Arseniy
  • 1,737
  • 1
  • 19
  • 35

6 Answers6

143

A long time ago:

Call any of these

byte[] org.apache.commons.io.FileUtils.readFileToByteArray(File file)
byte[] org.apache.commons.io.IOUtils.toByteArray(InputStream input) 

From

http://commons.apache.org/io/

If the library footprint is too big for your Android app, you can just use relevant classes from the commons-io library

Today (Java 7+ or Android API Level 26+)

Luckily, we now have a couple of convenience methods in the nio packages. For instance:

byte[] java.nio.file.Files.readAllBytes(Path path)

Javadoc here

Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
  • 10
    +1 - `IOUtils.toByteArray(InputStream)` will work too, though the `FileUtils` method should be more efficient. – Stephen C May 19 '11 at 11:43
  • but what if the content of the file IS the value of the byte array you want? – Adam Johns Jun 26 '14 at 20:26
  • @AdamJohns: Perfect material for a *new* question, here on Stack Overflow – Lukas Eder Jun 27 '14 at 07:43
  • 5
    How to do the same in Android ? byte[] java.nio.file.Files.readAllBytes(Path path) is not there in Andorid..? Any ideas..? – 3lokh May 06 '15 at 14:55
  • @NikhilGeorge: Use Apache Commons IO, or something similar as mentioned in the answer... There are also other answers here that show how to do this using the old `java.io.InputStream` API... – Lukas Eder May 06 '15 at 15:37
  • I have to disapprove with the edit concerning the java.nio package since it is not contained into the Android SDK! The android tag is definitly there so this answer is not correct. – AxelH Jun 05 '16 at 08:37
  • @AxelH: Sure, I added a remark. – Lukas Eder Jun 05 '16 at 17:16
  • Thanks, that's a bit more complete like this :) – AxelH Jun 06 '16 at 06:37
  • @StephenC At least in Commons IO 2.6, `FileUtils.readFileToByteArray` calls `IOUtils.toByteArray` under the hood. – Stephan Mar 06 '20 at 13:53
65

This will also work:

import java.io.*;

public class IOUtil {

    public static byte[] readFile(String file) throws IOException {
        return readFile(new File(file));
    }

    public static byte[] readFile(File file) throws IOException {
        // Open file
        RandomAccessFile f = new RandomAccessFile(file, "r");
        try {
            // Get and check length
            long longlength = f.length();
            int length = (int) longlength;
            if (length != longlength)
                throw new IOException("File size >= 2 GB");
            // Read file and return data
            byte[] data = new byte[length];
            f.readFully(data);
            return data;
        } finally {
            f.close();
        }
    }
}
Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
Paul
  • 651
  • 5
  • 2
  • The problem here could be a possible (unlikely) race condition (IMO). If you check f.length(), that is not necessarily the file you have opened, in case another application replaced it in the meantime. – sstn Mar 14 '12 at 10:32
  • 1
    @sstn but you have the same problem with all other solutions. – jcsahnwaldt Reinstate Monica Mar 16 '12 at 22:45
  • @ChristoperSanwaldt I don't know about the libraries, but manually reading into a ByteArrayOutputStream until you reach EOF would be safe (if the file would be locked for writing, don't know if java does sth. like that by default). – sstn Mar 19 '12 at 05:05
  • This is tagged android so I can't imagine this would be an issue in an android application – IcedDante Feb 28 '14 at 19:23
  • 12
    +1 for not adding a lib. – philipp Jul 15 '14 at 19:06
  • just tested it, and it is working! but thought I was able to just put it in my test project's MainActivity.java file, but it had to be placed in another class file (IOUtil.java). – Bigs Oct 26 '14 at 01:05
  • Great! I had the 65k method limit reached since I used Guava (which has 15k of methods itself). Made my code much smaller and fixed this issue. Thanks for a solution without libs. – Tobias Reich Oct 24 '16 at 09:17
  • it throws `java.lang.OutOfMemoryError: Failed to allocate a 258797515 byte allocation with 6994314 free bytes and 117MB until OOM` for 250MB file – Vasile Doe Oct 03 '17 at 11:52
40

If you use Google Guava (and if you don't, you should), you can call: ByteStreams.toByteArray(InputStream) or Files.toByteArray(File)

Peter Štibraný
  • 32,463
  • 16
  • 90
  • 116
  • 2
    But guava jar is 1.6mb, isn't that too big for an Android application? – Paulo Cesar Feb 26 '12 at 15:34
  • @PauloCesar: maybe. I'm not familiar with Android development, so I cannot comment on this. – Peter Štibraný Feb 26 '12 at 18:57
  • 2
    Sorry, I thought this question was related to Android, but now I realize it's just pure Java – Paulo Cesar Feb 26 '12 at 22:51
  • No, it's tagged Android. But Guava is required by Android client of Google's endpoints service, so I guess they think it is suitable for Android. And unused code will be removed in release build anyway. – Tom Mar 14 '13 at 20:44
  • 3
    @Tom is almost right. It won't be removed by default but if you setup Proguard it will remove all the unused code. Guava by default adds about 2.2MB at the time of this writing to an APK. But with Proguard it only added about 250KB. – yarian Oct 10 '13 at 17:55
17

This works for me:

File file = ...;
byte[] data = new byte[(int) file.length()];
try {
    new FileInputStream(file).read(data);
} catch (Exception e) {
    e.printStackTrace();
}
domsom
  • 3,163
  • 1
  • 22
  • 27
  • 5
    This method does not guarantee to read the whole file. – pihentagy Jan 14 '13 at 15:39
  • 2
    You're right, to be sure the return value of read() would have to be matched against file.length(), then continue reading if the file is not complete... – domsom Jan 15 '13 at 08:37
13

Use a ByteArrayOutputStream. Here is the process:

  • Get an InputStream to read data
  • Create a ByteArrayOutputStream.
  • Copy all the InputStream into the OutputStream
  • Get your byte[] from the ByteArrayOutputStream using the toByteArray() method
Vivien Barousse
  • 20,555
  • 2
  • 63
  • 64
  • i have an OutputStream so how to get the ByteArrayOutputStream from it (because i want to retrieve the byte[])? – Amira Dec 17 '13 at 14:58
7

Have a look at the following apache commons function:

org.apache.commons.io.FileUtils.readFileToByteArray(File)
timrau
  • 22,578
  • 4
  • 51
  • 64
BaSche
  • 394
  • 1
  • 6