2013-10-04 47 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。