2013-10-04 50 views
4

我知道安全的方式在资源来打开文件是:加载资源文件用的FileInputStream

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

现在的问题是,我的文件是在Weka的包装包决胜局的模型和 的Decider class只有一个方法:

public void load(File file) throws Exception 

负荷取文件,并打开它作为一个FileInputStream。你看到解决方法吗?我真的想 喜欢把模型放在资源中。我正在考虑创建一个临时文件,在临时文件中写入模型的内容,然后将临时文件传递给Weka,但它太脏了。 其他选项?

回答

6

我看到2个解决方案:

解决方案1 ​​

阅读类路径的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; 
     } 

    } 
} 

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