Загрузка файла в ресурсы с помощью FileInputStream
Я знаю безопасный способ открыть файл в ресурсах:
InputStream is = this.getClass().getResourceAsStream("/path/in/jar/file.name");
теперь проблема в том, что мой файл является моделью для решающего устройства в пакете Weka Wrapper и the вершитель класс имеет только метод:
public void load(File file) throws Exception
load берет файл и открывает его как FileInputStream. Ты видишь путь? Я бы очень хотел ... например, отправить модель, поместив ее в ресурсы. Я думал создать временный файл, написать содержимое модели в temp файл, а затем передать временный файл Weka, но это так грязно.. другие варианты?
1 ответов
Я вижу 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
если загрузчик классов, который загружает ресурс, является URLClassLoader, вы можете попытаться найти абсолютное имя файла. Но это!--11-->работает, только если ресурс, который вы хотите, существует в виде файла в файловой системе. Это не работает, если файл содержится в сосуд.
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);
}
}
Я бы предложил написать класс утилиты, который пытается найти абсолютный файл через загрузчик классов или, если он не может получить его таким образом, использует подход temp 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:// arch-file-uri[! absolute-path]
. Поскольку commons-vfs указывает собственный FileObject
это представляет собой файл, который вы все равно должны скопировать содержимое в локальный java.io.File
адаптироваться к Decider.load(File)
API-интерфейс.