File to byte[] in Java

2018-12-31 03:37发布

How do I convert a java.io.File to a byte[]?

标签: java file-io
21条回答
妖精总统
2楼-- · 2018-12-31 04:01

If you want to read bytes into a pre-allocated byte buffer, this answer may help.

Your first guess would probably be to use InputStream read(byte[]). However, this method has a flaw that makes it unreasonably hard to use: there is no guarantee that the array will actually be completely filled, even if no EOF is encountered.

Instead, take a look at DataInputStream readFully(byte[]). This is a wrapper for input streams, and does not have the above mentioned issue. Additionally, this method throws when EOF is encountered. Much nicer.

查看更多
笑指拈花
3楼-- · 2018-12-31 04:03
import java.io.RandomAccessFile;
RandomAccessFile f = new RandomAccessFile(fileName, "r");
byte[] b = new byte[(int)f.length()];
f.readFully(b);

Documentation for Java 8: http://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html

查看更多
临风纵饮
4楼-- · 2018-12-31 04:03

Guava has Files.toByteArray() to offer you. It has several advantages:

  1. It covers the corner case where files report a length of 0 but still have content
  2. It's highly optimized, you get a OutOfMemoryException if trying to read in a big file before even trying to load the file. (Through clever use of file.length())
  3. You don't have to reinvent the wheel.
查看更多
回忆,回不去的记忆
5楼-- · 2018-12-31 04:06

If you don't have Java 8, and agree with me that including a massive library to avoid writing a few lines of code is a bad idea:

public static byte[] readBytes(InputStream inputStream) throws IOException {
    byte[] b = new byte[1024];
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    int c;
    while ((c = inputStream.read(b)) != -1) {
        os.write(b, 0, c);
    }
    return os.toByteArray();
}

Caller is responsible for closing the stream.

查看更多
梦寄多情
6楼-- · 2018-12-31 04:08

Using the same approach as the community wiki answer, but cleaner and compiling out of the box (preferred approach if you don't want to import Apache Commons libs, e.g. on Android):

public static byte[] getFileBytes(File file) throws IOException {
    ByteArrayOutputStream ous = null;
    InputStream ios = null;
    try {
        byte[] buffer = new byte[4096];
        ous = new ByteArrayOutputStream();
        ios = new FileInputStream(file);
        int read = 0;
        while ((read = ios.read(buffer)) != -1)
            ous.write(buffer, 0, read);
    } finally {
        try {
            if (ous != null)
                ous.close();
        } catch (IOException e) {
            // swallow, since not that important
        }
        try {
            if (ios != null)
                ios.close();
        } catch (IOException e) {
            // swallow, since not that important
        }
    }
    return ous.toByteArray();
}
查看更多
无与为乐者.
7楼-- · 2018-12-31 04:09

Basically you have to read it in memory. Open the file, allocate the array, and read the contents from the file into the array.

The simplest way is something similar to this:

public byte[] read(File file) throws IOException, FileTooBigException {
    if (file.length() > MAX_FILE_SIZE) {
        throw new FileTooBigException(file);
    }
    ByteArrayOutputStream ous = null;
    InputStream ios = null;
    try {
        byte[] buffer = new byte[4096];
        ous = new ByteArrayOutputStream();
        ios = new FileInputStream(file);
        int read = 0;
        while ((read = ios.read(buffer)) != -1) {
            ous.write(buffer, 0, read);
        }
    }finally {
        try {
            if (ous != null)
                ous.close();
        } catch (IOException e) {
        }

        try {
            if (ios != null)
                ios.close();
        } catch (IOException e) {
        }
    }
    return ous.toByteArray();
}

This has some unnecessary copying of the file content (actually the data is copied three times: from file to buffer, from buffer to ByteArrayOutputStream, from ByteArrayOutputStream to the actual resulting array).

You also need to make sure you read in memory only files up to a certain size (this is usually application dependent) :-).

You also need to treat the IOException outside the function.

Another way is this:

public byte[] read(File file) throws IOException, FileTooBigException {
    if (file.length() > MAX_FILE_SIZE) {
        throw new FileTooBigException(file);
    }

    byte[] buffer = new byte[(int) file.length()];
    InputStream ios = null;
    try {
        ios = new FileInputStream(file);
        if (ios.read(buffer) == -1) {
            throw new IOException(
                    "EOF reached while trying to read the whole file");
        }
    } finally {
        try {
            if (ios != null)
                ios.close();
        } catch (IOException e) {
        }
    }
    return buffer;
}

This has no unnecessary copying.

FileTooBigException is a custom application exception. The MAX_FILE_SIZE constant is an application parameters.

For big files you should probably think a stream processing algorithm or use memory mapping (see java.nio).

查看更多
登录 后发表回答