使用FileInputStream在Resources中加载文件

我知道在资源中打开文件的安全方法是:

InputStream is = this.getClass().getResourceAsStream("/path/in/jar/file.name"); 

现在问题是我的文件是Weka Wrapper包中的decider的模型,而Decider类只有一个方法:

  public void load(File file) throws Exception 

load获取文件并将其作为FileInputStream打开。 你看到了解决方法吗? 我真的很想将模型发送到资源中。 我正在考虑创建一个临时文件,在临时文件中写入模型的内容,然后将临时文件传递给Weka,但它是如此脏..其他选项?

我看到2个解决方案:

解决方案1

将classpath ressource读取到临时文件并在调用load(File)后将其删除

 InputStream cpResource = this.getClass().getClassLoader().getResourceAsStream("file.name"); File tmpFile = File.createTempFile("file", "temp"); FileUtils.copyInputStreamToFile(cpResource, tmpFile); // FileUtils from apache-io try { decider.load(tmpFile); } finally { tmpFile.delete(); } 

解决方案2

如果加载资源的ClassLoader是URLClassLoader,您可以尝试查找绝对文件名。 但是, 只有当您想要的资源作为文件系统上的文件存在时,这才有效 。 如果文件包含在jar中,它不起作用。

 ClassLoader classLoader = this.getClass().getClassLoader(); if(classLoader instanceof URLClassLoader){ URLClassLoader urlClassLoader = URLClassLoader.class.cast(classLoader); URL resourceUrl = urlClassLoader.findResource("file.name"); if("file".equals(resourceUrl.getProtocol())){ URI uri = resourceUrl.toURI(); File file = new File(uri); decider.load(file); } } 

我建议编写一个实用程序类,尝试通过类加载器查找绝对文件,或者如果它无法通过这种方式使用临时文件方法作为回退。

或者以更加面向对象的方式:

  public class FileResourceTest { public static void main(String[] args) throws IOException { File resourceAsFile = getResourceAsFile("file.name"); System.out.println(resourceAsFile); } private static File getResourceAsFile(String resource) throws IOException { ClassLoader cl = FileResourceTest.class.getClassLoader(); File file = null; FileResource fileResource = new URLClassLoaderFileResource(cl, resource); try { file = fileResource.getFile(); } catch (IOException e) { fileResource = new ClasspathResourceFileResource(cl, resource); file = fileResource.getFile(); } return file; } public static interface FileResource { public File getFile() throws IOException; } public static class ClasspathResourceFileResource implements FileResource { private ClassLoader cl; private String resource; public ClasspathResourceFileResource(ClassLoader cl, String resource) { this.cl = cl; this.resource = resource; } public File getFile() throws IOException { InputStream cpResource = cl.getResourceAsStream(resource); File tmpFile = File.createTempFile("file", "temp"); FileUtils.copyInputStreamToFile(cpResource, tmpFile); tmpFile.deleteOnExit(); return tmpFile; } } public static class URLClassLoaderFileResource implements FileResource { private ClassLoader cl; private String resource; public URLClassLoaderFileResource(ClassLoader cl, String resourcePath) { this.cl = cl; this.resource = resourcePath; } public File getFile() throws IOException { File resourceFile = null; if (cl instanceof URLClassLoader) { URLClassLoader urlClassLoader = URLClassLoader.class.cast(cl); URL resourceUrl = urlClassLoader.findResource(resource); if ("file".equals(resourceUrl.getProtocol())) { try { URI uri = resourceUrl.toURI(); resourceFile = new File(uri); } catch (URISyntaxException e) { IOException ioException = new IOException( "Unable to get file through class loader: " + cl); ioException.initCause(e); throw ioException; } } } if (resourceFile == null) { throw new IOException( "Unable to get file through class loader: " + cl); } return resourceFile; } } } 

您还可以使用像commons-vfs这样的第三方库 ,它允许您引用jar中的文件。 例如jar:// arch-file-uri[! absolute-path] jar:// arch-file-uri[! absolute-path] 。 由于commons-vfs指定了一个代表文件的自己的FileObject ,因此您仍必须将内容复制到本地java.io.File以适应Decider.load(File) API。