简体   繁体   中英

Why does getResourceAsStream() and reading file with FileInputStream return arrays of different length?

I want to read files as byte arrays and realised that amount of read bytes varies depending on the used method. Here the relevant code:

    public byte[] readResource() {
    try (InputStream is = getClass().getClassLoader().getResourceAsStream(FILE_NAME)) {
        int available = is.available();
        byte[] result = new byte[available];
        is.read(result, 0, available);

        return result;
    } catch (Exception e) {
        log.error("Failed to load resource '{}'", FILE_NAME, e);
    }

    return new byte[0];
}

public byte[] readFile() {
    File file = new File(FILE_PATH + FILE_NAME);
    try (InputStream is = new FileInputStream(file)) {
        int available = is.available();
        byte[] result = new byte[available];
        is.read(result, 0, available);

        return result;
    } catch (Exception e) {
        log.error("Failed to load file '{}'", FILE_NAME, e);
    }

    return new byte[0];
}

Calling File.length() and reading with the FileInputStream returns the correct length of 21566 bytes for the given test file, though reading the file as a resources returns 21622 bytes.

Does anyone know why I get different results and how to fix it so that readResource() returns the correct result?

Why does getResourceAsStream() and reading file with FileInputStream return arrays of different length?

Because you're misusing the available() method in a way that is specifically warned against in the Javadoc :

"It is never correct to use the return value of this method to allocate a buffer intended to hold all data in this stream."

and

Does anyone know why I get different results and how to fix it so that readResource() returns the correct result?

Read in a loop until end of stream.

According to the the API docs of InputStream, InputStream.available() does not return the size of the resource - it returns

an estimate of the number of bytes that can be read (or skipped over) from this input stream without blocking

To get the size of a resource from a stream, you need to fully read the stream, and count the bytes read.

To read the stream and return the contents as a byte array, you could do something like this:

    try (   InputStream is = getClass().getClassLoader().getResourceAsStream(FILE_NAME);
            ByteArrayOutputStream bos = new ByteArrayOutputStream()) {

        byte[] buffer = new byte[4096];
        int bytesRead = 0;
        while ((bytesRead = is.read(buffer)) != -1) {
            bos.write(buffer, 0, bytesRead);
        }
        return bos.toByteArray();

    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM