检测java.lang.Class.getResourceAsStream()打开的目录

检测java.lang.Class.getResourceAsStream()打开的目录,java,io,Java,Io,假设类路径中有以下资源: /res/image/logo.png /res/image/splash.png 然后,可以使用以下方法获取logo.png的InputStream: SomeClass.class.getResourceAsStream("/res/image/logo.png"); 如果请求的资源不存在,getResourceAsStream()将返回null 但是,如果您请求的资源实际上是一个目录,则不会得到null或异常:您实际上会得到一个java.io.ByteArra

假设类路径中有以下资源:

/res/image/logo.png
/res/image/splash.png
然后,可以使用以下方法获取logo.png的
InputStream

SomeClass.class.getResourceAsStream("/res/image/logo.png");
如果请求的资源不存在,
getResourceAsStream()
将返回null

但是,如果您请求的资源实际上是一个目录,则不会得到null或异常:您实际上会得到一个
java.io.ByteArrayInputStream
。从这个流中转储字节后,它似乎是该目录中的资源列表(每行一个)

因此:

给出一个
ByteArrayInputStream
,转储时包含:

logo.png
splash.png
是否有可靠的方法来确定由
getResourceAsStream()
打开的资源实际上是一个目录?或者以其他方式访问类路径资源,这样就可以了?(也许可以通过某种方式使用
getResource()
完成吗?)

更新:

出于兴趣,我调用了
getResource()
,并转储了一个“资源”的URL,而我知道该“资源”在磁盘上并不作为文件存在(在本例中为
/java/util/List.class
)。以下是我得到的:

jar:file:/C:/projects/<my_proj>/env/jdk/jre/lib/rt.jar!/java/util/List.class
因此,如果资源的URL不是“文件:”资源,则可以将
null
视为(公认是间接的,也许不可靠)指示“资源”是目录。如果是建议的解决方案,则可以使用
文件。isDirectory()


我想这个黑客会有用的。我不确定我是否会在真正的代码中使用它!;-)

据我所知,getResourceAsStream没有办法,但您可以随时通过使用
getResource
获取URL来检查它是否是文件或目录,然后获取路径,然后
新建文件(路径)。isDirectory()
新建文件(路径)。isFile()
getResource()提供URL。检查该URL,如果它以“file://”开头,则可以提取文件名,并调用
newfile(name).isDirectory()

如果它不是以“file://”开头,则它位于web服务器后面,并且没有标准的方法来确定资源是否是目录

附录

尝试将“/”或“/…”添加到URL中-如果表示的资源存在,则URL引用目录。

您可以执行以下操作:

URL resource = getClass().getResource("/res/image");
File folder = new File(new URI(resource.getPath()).getPath());
if(folder.isDirectory()) {
    // do something
}

测试
getResource()
的非
null
结果作为目录非常简单:只需检查它是否以
“/”
(斜杠)结尾

如果您不信任这个简单的检查,那么您必须对每个协议分别执行检查。对于
文件:
URL,有一种安全的方法:

URL url = Foo.class.getResource(".");
if(url.getProtocol().equals("file"))
{
  boolean dir=new File(url.toURI()).isDirectory();
}

对其他人来说,这并不明显。有些协议甚至可能没有目录的概念(或者文件和目录之间的区别)。对于
JAR
文件,您通常会得到
null
,因为
JAR
文件通常不包含目录项。

您可以通过类检测
InputStream
是文件还是目录。如果它是一个文件,它将是一个“BufferedInputStream”,目录将是一个“ByteArrayInputStream”

例如:

InputStream is = SomeClass.class.getResourceAsStream("/res/image");
boolean isDirectory = isDirectory(is); //true

这是一个有趣的问题,但你是否有一个实际应用的想法,或者只是学术兴趣?是的,我有一个实际应用(和一些失败的单元测试)。我定义了一个(最小的)
Store
接口,它隐藏了各种类型的“文件系统”。例如,在我们的在线帮助系统中,我想为帮助servlet提供一个帮助文件存储。它不应该关心存储是文件目录、zip/jar文件还是类路径上资源的子集。我有一套单元测试来检查我编写的四个实现的行为是否相同。一个测试断言您无法打开存储中的目录,但对于基于资源的实现来说,这失败了。您看过Spring的资源和扫描支持吗?我不知道您的用例的细节,但它可能已经具备了您需要的功能。不知道它在我的applications.jar文件中,或者在我的应用程序的类路径中的某个其他.jar文件中。
URL url = Foo.class.getResource(".");
if(url.getProtocol().equals("file"))
{
  boolean dir=new File(url.toURI()).isDirectory();
}
public boolean isDirectory(InputStream is) {
  return is.getClass().getSimpleName().equals("ByteArrayInputStream");
}

public boolean isFile(InputStream is) {
  return is.getClass().getSimpleName().equals("BufferedInputStream");
}
InputStream is = SomeClass.class.getResourceAsStream("/res/image");
boolean isDirectory = isDirectory(is); //true