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? :)

0

6 Answers 6

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

Sign up to request clarification or add additional context in comments.

8 Comments

+1 - IOUtils.toByteArray(InputStream) will work too, though the FileUtils method should be more efficient.
but what if the content of the file IS the value of the byte array you want?
@AdamJohns: Perfect material for a new question, here on Stack Overflow
How to do the same in Android ? byte[] java.nio.file.Files.readAllBytes(Path path) is not there in Andorid..? Any ideas..?
@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...
|
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();
        }
    }
}

8 Comments

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 but you have the same problem with all other solutions.
@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).
This is tagged android so I can't imagine this would be an issue in an android application
+1 for not adding a lib.
|
40

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

5 Comments

But guava jar is 1.6mb, isn't that too big for an Android application?
@PauloCesar: maybe. I'm not familiar with Android development, so I cannot comment on this.
Sorry, I thought this question was related to Android, but now I realize it's just pure Java
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 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.
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();
}

2 Comments

This method does not guarantee to read the whole file.
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...
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

1 Comment

i have an OutputStream so how to get the ByteArrayOutputStream from it (because i want to retrieve the byte[])?
7

Have a look at the following apache commons function:

org.apache.commons.io.FileUtils.readFileToByteArray(File)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.