Jars - это не что иное, как Zip-файлы, и Java обеспечивает поддержку для их обработки.
Java 6 (и ранее)
Вы можете открыть файл банку в качестве ZipFile
и перебирать записи этого. Каждая запись имеет полное имя пути внутри файла, нет такой вещи, как относительные имена путей. Хотя вам нужно позаботиться о том, чтобы все записи, хотя были абсолютными в zip-файле, не начинались с символа '/', если вам это нужно, вы должны добавить его. Следующий фрагмент даст вам путь к файлу класса. className
должен заканчиваться .class
, т.е. LanguageDetection.class
String getPath(String jar, String className) throws IOException {
final ZipFile zf = new ZipFile(jar);
try {
for (ZipEntry ze : Collections.list(zf.entries())) {
final String path = ze.getName();
if (path.endsWith(className)) {
final StringBuilder buf = new StringBuilder(path);
buf.delete(path.lastIndexOf('/'), path.length()); //removes the name of the class to get the path only
if (!path.startsWith("/")) { //you may omit this part if leading/is not required
buf.insert(0, '/');
}
return buf.toString();
}
}
} finally {
zf.close();
}
return null;
}
Java 7/8
Вы можете открыть файл JAR, используя поддержку Java7 FileSystem для JAR-файлов. Это позволяет работать с файлом jar, как если бы это была обычная FileSystem. Таким образом, вы можете пройти fileTree до тех пор, пока не найдете свой файл и не получите путь от него. В следующем примере используются потоки Java8 и Lambdas, версия для Java7 может быть получена из этого, но будет немного больше.
Path jarFile = ...;
Map<String, String> env = new HashMap<String, String>() {{
put("create", "false");
}};
try(FileSystem zipFs = newFileSystem(URI.create("jar:" + jarFileFile.toUri()), env)) {
Optional<Path> path = Files.walk(zipFs.getPath("/"))
.filter(p -> p.getFileName().toString().startsWith("LanguageDetection"))
.map(Path::getParent)
.findFirst();
path.ifPresent(System.out::println);
}
вашей конкретной проблемы
Вышеуказанные решения для нахождения пути внутри Jar или Zip, но, возможно, не будет решением вашей проблемы.
Я не уверен, правильно ли я понимаю вашу проблему. Насколько мне известно, вы хотите иметь доступ к пути внутри каталога классов для любых целей. Проблема в том, что механизм поиска класса/ресурса не применяется к папкам, только к файлам. Близкая концепция - это пакет, но это всегда связано с классом.
Таким образом, вам всегда нужен конкретный файл для доступа через метод getResource()
. Например, MyClass.class.getResource(/path/to/resource.txt)
.
Если ресурсы расположены в profiles.sm
папки по отношению к классу и его упаковки, т.е. в /com/languagedetect/profile.sm/
можно построить путь от эталонного класса, например, класс LanguageDetection
в этом пакете и получить абсолютный путь от этого к профилей.см путь:
String basePath = "/" + LanguageDetection.class.getPackage().getName().replaceAll("\\.", "/") + "/profiles.sm/";
URL resource = LanguageDetection.class.getResource(basePath + "myResource.txt");
Если есть только один profiles.sm
в корне баночки, просто пойти на
String basePath = "/profiles.sm/";
URL resource = LanguageDetection.class.getResource(basePath + "myResource.txt");
Если у вас есть несколько банок с ресурсом в /profiles.sm
, вы можете получить доступ ко всем из тех, с помощью загрузчика классов, а затем извлечь файл Jar из URL класса
for(URL u : Collections.list(LanguageDetection.class.getClassLoader().getResources("/profiles.sm/yourResource"))){
System.out.println(u);
}
в любом случае это невозможно без доступа к файлу почтового индекса/банка с просмотрите содержимое этого пути или папки, потому что Java не поддерживает просмотр классов или ресурсов внутри пакета/папки в пути к классам. Вы можете использовать библиотеку Reflections для этого или расширить пример ClassLoader выше, дополнительно прочитав содержимое обнаруженных банок, используя пример zip сверху.
Вы взглянули на этот? может помочь http://stackoverflow.com/questions/573679/open-resource-with-relative-path-in-java; jar или нет - это то же самое, если оно находится в пути к классам – Preuk
. Я попытался использовать DetectorFactory.loadProfile (LanguageDetection.class.getResource ("profiles.sm"). getPath()); но не помогает –