16

我已经为此搜索了很长时间,但所有结果都指向 Java 7 之前的 NIO 解决方案。我已经使用NIO 的东西从文件系统上的特定位置读取文件,这比以前容易多了(Files.readAllBytes(path))。现在,我想读入一个打包在我的 WAR 和类路径中的文件。我们目前使用类似于以下的代码来执行此操作:

Input inputStream = this.getClass().getClassLoader().getResourceAsStream(fileName);
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();

/* iterate through the input stream to get all the bytes (no way to reliably find the size of the 
 *     file behind the inputStream (see http://docs.oracle.com/javase/6/docs/api/java/io/InputStream.html#available()))
 */
int byteInt = -1;
try
{
    byteInt = inputStream.read();
    while (byteInt != -1)
    {
        byteStream.write(byteInt);
        byteInt = inputStream.read();
    }

    byteArray = byteStream.toByteArray();
    inputStream.close();
    return byteArray;
}
catch (IOException e)
{
    //...
}

虽然这可行,但我希望有一种更简单/更好的方法来使用 Java 7 中的 NIO 东西来做到这一点。我猜我需要在类路径上获取一个表示该路径的Path对象,但我是不知道该怎么做。

如果这是一些超级简单的事情,我深表歉意。我就是想不通。谢谢您的帮助。

4

4 回答 4

30

这对我有用。

import java.nio.file.Files;
import java.nio.file.Paths;

// fileName: foo.txt which lives under src/main/resources
public String readFileFromClasspath(final String fileName) throws IOException, URISyntaxException {
    return new String(Files.readAllBytes(
                Paths.get(getClass().getClassLoader()
                        .getResource(fileName)
                        .toURI())));
}
于 2015-03-04T16:51:57.047 回答
8

Path 代表文件系统上的一个文件。从类路径中读取资源没有帮助。您正在寻找的是一个辅助方法,它从流中读取所有内容(比您的操作更有效)并将其写入字节数组。Apache commons-io 或 Guava 可以帮助你。以番石榴为例:

byte[] array = 
    ByteStreams.toByteArray(this.getClass().getClassLoader().getResourceAsStream(resourceName));

如果您不想仅仅为此将 Guava 或 commons-io 添加到您的依赖项中,您可以随时阅读它们的源代码并将其复制到您自己的辅助方法中。

于 2013-02-04T18:24:52.740 回答
2

据我了解,你想要的是打开ReadableByteChannel你的资源,所以你可以使用 NIO 来阅读它。

这应该是一个好的开始

// Opens a resource from the current class' defining class loader
InputStream istream = getClass().getResourceAsStream("/filename.txt");

// Create a NIO ReadableByteChannel from the stream
ReadableByteChannel channel = java.nio.channels.Channels.newChannel(istream);
于 2013-02-04T18:24:43.163 回答
1

你应该看看ClassLoader.getResource()。这将返回一个代表资源的 URL。如果它是文件系统的本地文件,它将是一个file://URL。那时你可以去掉方案等,然后你就有了文件名,你可以用它做任何你想做的事情。

但是,如果它不是 file:// 路径,那么您可以回退到正常的 InputStream。

于 2013-02-04T18:22:15.350 回答