使用FileInputStream在Resources中加载文件 [英] Load a file in Resources with FileInputStream

查看:3489
本文介绍了使用FileInputStream在Resources中加载文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I know the safe way to open a file in the resources is:

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

现在问题是我的文件是Weka Wrapper包中的决策者的模型和
Decider类只有一个方法:

now the problem is that my file is a model for a decider in the Weka Wrapper package and the Decider class has only a method:

  public void load(File file) throws Exception 

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

load takes the file and opens it as a FileInputStream. Do you see a workaround? I really would like to ship the model putting it in the resources. I was thinking to create a temporary file, write the content of the model in the temp file and then pass the temporary file to Weka, but it is so dirty.. other options?

推荐答案

我看到2个解决方案:

解决方案1

将类路径资源读取到临时文件并在调用 load(文件)后删除它

Read the classpath ressource to a temp file and delete it after you called 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中,它就不起作用。

If the ClassLoader that loads the resource is a URLClassLoader you can try to find the absolute file name. But this only works if the resource you want exists as a file on the filesystem. It doesn't work if the file is contained in a 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);
    }
}

我建议写一个试用的实用工具类通过类加载器找到绝对文件,或者如果它不能以这种方式获取它,则使用临时文件方法作为后备。

I would suggest to write a utility class that tries to find the absolute file through the class loader or if it can't get it this way uses the temp file approach as fallback.

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

Or in a more object-oriented way:

    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 [!绝对路径] 。由于commons-vfs指定了自己的 FileObject 代表一个文件,你仍然必须将内容复制到本地 java.io.File 以适应决策者.load(文件) API。

You can also use a thrid party library like commons-vfs that allows you to reference a file within a jar. E.g. jar:// arch-file-uri[! absolute-path]. Since commons-vfs specifies an own FileObject that represents a file you must still copy the content to a local java.io.File to adapt to the Decider.load(File) API.

这篇关于使用FileInputStream在Resources中加载文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆