Я сталкивался с этой же проблемой несколько раз раньше.
В JDK 7 я надеялся, что кто-то напишет файловую систему classpath, но, увы, пока нет.
Spring имеет класс Resource, который позволяет вам очень приятно загружать ресурсы classpath.
Ответы были очень хорошими, но я подумал, что могу добавить к обсуждению пример с файлами и каталогами, которые являются ресурсами classpath.
Я написал небольшой прототип, чтобы решить эту проблему. Прототип не обрабатывает каждый крайний случай, но он обрабатывает поиск ресурсов в каталогах, которые находятся в jar-файлах.
Я довольно давно использовал переполнение стека. Это первый раз, когда я помню, как отвечаю на вопрос, так что прости меня, если я пойду долго (это моя натура).
<code>
package com.foo;
import java.io.File;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URI;
import java.net.URL;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
* Prototype resource reader.
* This prototype is devoid of error checking.
*
*
* I have two prototype jar files that I have setup.
* <pre>
* <dependency>
* <groupId>invoke</groupId>
* <artifactId>invoke</artifactId>
* <version>1.0-SNAPSHOT</version>
* </dependency>
*
* <dependency>
* <groupId>node</groupId>
* <artifactId>node</artifactId>
* <version>1.0-SNAPSHOT</version>
* </dependency>
*
* Каждый из jar-файлов имеет файл в / org / node / с именем resource.txt.
*
* Это всего лишь прототип того, как будет выглядеть обработчик с classpath: //
* У меня также есть resource.foo.txt в моих локальных ресурсах для этого проекта.
*
* /
открытый класс ClasspathReader {
public static void main (String [] args) выдает Exception {
/ * Этот проект включает в себя два файла JAR, каждый из которых имеет ресурс, расположенный
в / org / node / называется resource.txt.
* /
/ *
Пространство имен - это просто устройство, которое я использую, чтобы увидеть, есть ли файл в каталоге
начинается с пространства имен. Думайте о пространстве имен как о расширении файла
но это начало файла, а не конец.
* /
String namespace = "resource";
// someResource является classpath.
Строка someResource = args.length> 0? args [0]:
//"classpath:///org/node/resource.txt "; Работает с файлами
"Путь к классам: /// орг / узел /"; // Также работает с каталогами
URI someResourceURI = URI.create (someResource);
System.out.println ("URI ресурса =" + someResourceURI);
someResource = someResourceURI.getPath ();
System.out.println ("ПУТЬ ресурса =" + someResource);
boolean isDir =! someResource.endsWith (". txt");
/ ** Ресурс Classpath никогда не может начинаться с начального слеша.
* Логически они делают, но на самом деле вы должны раздеть это.
* Это известное поведение ресурсов classpath.
* Он работает с косой чертой, если ресурс не находится в файле JAR.
* Итог, удаляя его, он всегда работает.
* /
if (someResource.startsWith ("/")) {
someResource = someResource.substring (1);
}
/ * Используйте ClassLoader для поиска всех ресурсов, которые имеют это имя.
Ищите все ресурсы, которые соответствуют местоположению, которое мы ищем. * /
Ресурсы перечисления = ноль;
/ * Сначала проверьте контекстный загрузчик классов. Всегда используйте это, если доступно. * /
пытаться {
ресурсы =
. Thread.currentThread () getContextClassLoader () GetResources (someResource).
} catch (Exex ex) {
ex.printStackTrace ();
}
if (resources == null ||! resources.hasMoreElements ()) {
resources = ClasspathReader.class.getClassLoader (). getResources (someResource);
}
// Теперь перебираем URL ресурсов из пути к классам
while (resources.hasMoreElements ()) {
URL resource = resources.nextElement ();
/ * если ресурс представляет собой файл, это просто означает, что мы можем использовать обычный механизм
сканировать каталог.
* /
if (resource.getProtocol (). equals ("file")) {
// если это файл, то мы можем обработать его обычным способом.
handleFile (ресурс, пространство имен);
Продолжить;}
System.out.println («Ресурс» + ресурс);
/ *
Разделите строку, которая выглядит следующим образом:
баночка: файл! /Users/rick/.m2/repository/invoke/invoke/1.0-SNAPSHOT/invoke-1.0-SNAPSHOT.jar / орг / узел /
в
это /Users/rick/.m2/repository/invoke/invoke/1.0-SNAPSHOT/invoke-1.0-SNAPSHOT.jar
и это
/ Орг / узел /
* /
String [] split = resource.toString (). Split (":");
String [] split2 = split [2] .split ("!");
String zipFileName = split2 [0];
String sresource = split2 [1];
System.out.printf («Имя файла после разделения zip =% s,» +
"\ nresource in zip% s \ n", zipFileName, sresource);
/ * Откройте zip-файл. * /
ZipFile zipFile = новый ZipFile (zipFileName);
/ * Перебирать записи. * /
Записи перечисления = zipFile.entries ();
while (records.hasMoreElements ()) {
ZipEntry entry = records.nextElement ();
/ * Если это каталог, пропустите его. * /
if (entry.isDirectory ()) {
Продолжить;
}
String entryName = entry.getName ();
System.out.printf ("имя записи zip% s \ n", entryName);
/ * Если он не начинается с нашей строки someResource
тогда это не наш ресурс, так что продолжайте.
* /
if (! entryName.startsWith (someResource)) {
Продолжить;
}
/ * часть fileName из имени записи.
* где /foo/bar/foo/bee/bar.txt, bar.txt - это файл
* /
String fileName = entryName.substring (entryName.lastIndexOf ("/") + 1);
System.out.printf ("имя_файла% s \ n", имя_файла);
/ * Посмотрим, начинается ли файл с нашего пространства имен и заканчивается нашим расширением.
* /
if (fileName.startsWith (namespace) && fileName.endsWith (". txt")) {
/ * Если вы нашли файл, распечатайте
содержимое файла в System.out. * /
try (Reader reader = new InputStreamReader (zipFile.getInputStream (entry))) {
StringBuilder builder = new StringBuilder ();
int ch = 0;
while ((ch = reader.read ())! = -1) {
builder.append ((char) ch);
}
System.out.printf ("zip fileName =% s \ n \ n #### \ n содержимое файла% s \ n ### \ n", entryName, builder);
} catch (Exex ex) {
ex.printStackTrace ();
}
}
// используем запись, чтобы увидеть, является ли это файл «1.txt»
// Чтение из байта с использованием file.getInputStream (entry)
}
}
}
/ **
* Файл находился в файловой системе, а не в zip-файле,
* это здесь для полноты для этого примера.
* иначе.
*
ресурс @param
* @param namespace
* Исключения @throws
* /
приватный статический void handleFile (ресурс URL, пространство имен String) выдает исключение {
System.out.println («Обрабатывать этот ресурс как файл» + ресурс);
URI uri = resource.toURI ();
Файл файл = новый файл (uri.getPath ());
if (file.isDirectory ()) {
for (Файл childFile: file.listFiles ()) {
if (childFile.isDirectory ()) {
Продолжить;
}String fileName = childFile.getName ();
if (fileName.startsWith (пространство имен) && fileName.endsWith ("txt")) {
try (FileReader reader = new FileReader (childFile)) {
StringBuilder builder = new StringBuilder ();
int ch = 0;
while ((ch = reader.read ())! = -1) {
builder.append ((char) ch);
}
System.out.printf ("fileName =% s \ n \ n #### \ n содержимое файла% s \ n ### \ n", childFile, строитель);
} catch (Exex ex) {
ex.printStackTrace ();
}
}
}
} еще {
Строка fileName = file.getName ();
if (fileName.startsWith (пространство имен) && fileName.endsWith ("txt")) {
try (FileReader Reader = новый FileReader (файл)) {
StringBuilder builder = new StringBuilder ();
int ch = 0;
while ((ch = reader.read ())! = -1) {
builder.append ((char) ch);
}
System.out.printf ("fileName =% s \ n \ n #### \ n содержимое файла% s \ n ### \ n", fileName, строитель);
} catch (Exex ex) {
ex.printStackTrace ();
}
}
}
}
}
Здесь вы можете увидеть более полный пример с примером вывода.