How to load a classpath resource to an array of byte?

59,560

Solution 1

Have a look at Google guava ByteStreams.toByteArray(INPUTSTREAM), this is might be what you want.

Solution 2

Java 9 native implementation:

byte[] data = this.getClass().getClassLoader().getResourceAsStream("/assets/myAsset.bin").readAllBytes();

Solution 3

Although i agree with Andrew Thompson, here is a native implementation that works since Java 7 and uses the NIO-API:

byte[] data = Files.readAllBytes(Paths.get(this.getClass().getClassLoader().getResource("/assets/myAsset.bin").toURI()));

Solution 4

Take a look at Apache IOUtils - it has a bunch of methods to work with streams

Solution 5

I usually use the following two approaches to convert Resource into byte[] array.

1 - approach

What you need is to first call getInputStream() on Resource object, and then pass that to convertStreamToByteArray method like below....

InputStream stream = resource.getInputStream();
long size = resource.getFile().lenght();

byte[] byteArr = convertStreamToByteArray(stream, size);

public byte[] convertStreamToByteArray(InputStream stream, long size) throws IOException {

    // check to ensure that file size is not larger than Integer.MAX_VALUE.
    if (size > Integer.MAX_VALUE) {
        return new byte[0];
    }

    byte[] buffer = new byte[(int)size];
    ByteArrayOutputStream os = new ByteArrayOutputStream();

    int line = 0;
    // read bytes from stream, and store them in buffer
    while ((line = stream.read(buffer)) != -1) {
        // Writes bytes from byte array (buffer) into output stream.
        os.write(buffer, 0, line);
    }
    stream.close();
    os.flush();
    os.close();
    return os.toByteArray();
}

2 - approach

As Konstantin V. Salikhov suggested, you could use org.apache.commons.io.IOUtils and call its IOUtils.toByteArray(stream) static method and pass to it InputStream object like this...

byte[] byteArr = IOUtils.toByteArray(stream);

Note - Just thought I'll mention this that under the hood toByteArray(...) checks to ensure that file size is not larger than Integer.MAX_VALUE, so you don't have to check for this.

Share:
59,560
Samuel Rossille
Author by

Samuel Rossille

Updated on July 09, 2022

Comments

  • Samuel Rossille
    Samuel Rossille almost 2 years

    I know how to get the inputstream for a given classpath resource, read from the inputstream until i reach the end, but it looks like a very common problem, and i wonder if there an API that I don't know, or a library that would make things as simple as

    byte[] data = ResourceUtils.getResourceAsBytes("/assets/myAsset.bin")
    

    or

    byte[] data = StreamUtils.readStreamToEnd(myInputStream)
    

    for example!

    • Andrew Thompson
      Andrew Thompson almost 12 years
      "it looks like a very common problem" Commonly Java methods will accept an InputStream.
    • Louis Wasserman
      Louis Wasserman almost 12 years
      I think that with Guava, this is more or less Resources.toByteArray(Resources.getResource(contextClass, resourceName))?
    • Samuel Rossille
      Samuel Rossille almost 12 years
      @AndrewThompson you just prevented me from doing something stupid in this precise case, thank you.
    • Andrew Thompson
      Andrew Thompson almost 12 years
      Entered as (alternate) answer. ;)
  • Pablo Thiele
    Pablo Thiele over 8 years
    Good approach but I think that you means convertStreamToByteArray instead of Steam. :) Nice answer.
  • yunandtidus
    yunandtidus over 8 years
    more precisely something as IOUtils.toByteArray(getClass().getClassLoader().getResourceA‌​sStream("XXX")
  • Simple-Solution
    Simple-Solution over 7 years
    @PabloRS I've rectified the typo. Ta :)
  • cesAR
    cesAR over 7 years
    This is useful for me in 2016. I am using the latest version of IOUtils with Maven: https://mvnrepository.com/artifact/commons-io/commons-io/2.5‌​, through the suggestion of @yunandtidus Thanks.
  • Innokenty
    Innokenty over 2 years
    My favourite is IOUtils.resourceToByteArray("XXX", getClass().getClassLoader()) as it's a tiny bit shorter.
  • Joe White
    Joe White over 2 years
    If I'm running from a JAR, this fails with a FileSystemNotFoundException. I can get it to work by registering the JAR as a filesystem using FileSystems.newFileSystem, but I have to do that for each JAR I want to read resources from.
  • ltlBeBoy
    ltlBeBoy about 2 years
    @JoeWhite Depending on the environment it may be required to remove the leading slash. E.g. in newer versions of Payara application server the class loader is able to find the resources only if it's a relative path.