如何将类路径资源加载到字节数组?

Posted

技术标签:

【中文标题】如何将类路径资源加载到字节数组?【英文标题】:How to load a classpath resource to an array of byte? 【发布时间】:2012-06-04 11:14:19 【问题描述】:

我知道如何获取给定类路径资源的输入流,从输入流中读取直到我到达末尾,但这看起来是一个非常常见的问题,并且我想知道是否有我不知道的 API,或者可以使事情变得如此简单的库

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

byte[] data = StreamUtils.readStreamToEnd(myInputStream)

例如!

【问题讨论】:

“这看起来是个很常见的问题” Java 方法通常会接受 InputStream 认为对于 Guava,这或多或少是 Resources.toByteArray(Resources.getResource(contextClass, resourceName))? @AndrewThompson 你只是阻止我在这种情况下做一些愚蠢的事情,谢谢。 作为(替代)答案输入。 ;) 【参考方案1】:

虽然我同意 Andrew Thompson 的观点,但这是一个从 Java 7 开始工作并使用 NIO-API 的本机实现:

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

【讨论】:

如果我从 JAR 运行,则会失败并出现 FileSystemNotFoundException。我可以通过使用 FileSystems.newFileSystem 将 JAR 注册为文件系统来使其工作,但我必须为每个要从中读取资源的 JAR 执行此操作。【参考方案2】:

Java 9 原生实现:

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

【讨论】:

【参考方案3】:

我通常使用以下两种方法将Resource转换为byte[]数组。

1 - 接近

您需要首先在Resource 对象上调用getInputStream(),然后将其传递给convertStreamToByteArray 方法,如下所示......

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 - 接近

正如 Konstantin V. Salikhov 建议的那样,您可以使用 org.apache.commons.io.IOUtils 并调用其 IOUtils.toByteArray(stream) static 方法并将 InputStream 对象传递给它...

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

Note - 只是想我会提到这一点,toByteArray(...) 会检查以确保文件大小不大于Integer.MAX_VALUE,因此您不必检查这一点。

【讨论】:

好方法,但我认为你的意思是 convertStreamToByteArray 而不是 Steam。 :) 不错的答案。 @PabloRS 我已经纠正了错字。塔:)【参考方案4】:

常见的 Java 方法将接受 InputStream。在大多数情况下,我建议将流直接传递给感兴趣的方法。

许多相同的方法也将接受URL(例如,从getResource(String) 获得)。这有时会更好,因为各种方法都需要可重新定位的InputStream,而且有时从getResourceAsStream(String) 返回的流不可是可重新定位的。

【讨论】:

【参考方案5】:

看看 Google guava ByteStreams.toByteArray(INPUTSTREAM),这可能就是你想要的。

【讨论】:

【参考方案6】:

看看 Apache IOUtils - 它有很多处理流的方法

【讨论】:

更准确地说是IOUtils.toByteArray(getClass().getClassLoader().getResourceAsStream("XXX") 这对我在 2016 年很有用。我正在使用最新版本的 IOUtils 和 Maven:https://mvnrepository.com/artifact/commons-io/commons-io/2.5,通过 @yunandtidus 的建议谢谢。 我最喜欢的是IOUtils.resourceToByteArray("XXX", getClass().getClassLoader()),因为它有点短。

以上是关于如何将类路径资源加载到字节数组?的主要内容,如果未能解决你的问题,请参考以下文章

关于类的加载机制和反射机制只看这一篇就够了,分析的非常详细

《Spring揭秘》——IOC梳理3(资源加载,国际化)

Apptication的其他功能

从服务器加载文件到内存

如何使用 informix.jvp.dbapplet.impl.JVPClassLoader 从类路径加载资源?

如何将资源文件夹中的图像加载到android listview中