現在のJARファイルのディレクトリ内のファイルのリスト
質問
JAVAでゲームを作成しているときに、jar内の特定のディレクトリにあるファイルのリストを作成して、ゲームで使用するクラスのリストを確実に作成できるようにします。
たとえば、私のjarにディレクトリがあるとします
mtd/entity/creep/
そのディレクトリ内のすべての.classファイルのリストを取得したい jar内の別のクラスのJavaコードを使用。
そうするのに最適なコードは何ですか?
解決
古いjava1.4コード、しかしそれはあなたにアイデアを与えるでしょう:
private static List getClassesFromJARFile(String jar, String packageName) throws Error
{
final List classes = new ArrayList();
JarInputStream jarFile = null;
try
{
jarFile = new JarInputStream(new FileInputStream(jar));
JarEntry jarEntry;
do
{
try
{
jarEntry = jarFile.getNextJarEntry();
}
catch(IOException ioe)
{
throw new CCException.Error("Unable to get next jar entry from jar file '"+jar+"'", ioe);
}
if (jarEntry != null)
{
extractClassFromJar(jar, packageName, classes, jarEntry);
}
} while (jarEntry != null);
closeJarFile(jarFile);
}
catch(IOException ioe)
{
throw new CCException.Error("Unable to get Jar input stream from '"+jar+"'", ioe);
}
finally
{
closeJarFile(jarFile);
}
return classes;
}
private static void extractClassFromJar(final String jar, final String packageName, final List classes, JarEntry jarEntry) throws Error
{
String className = jarEntry.getName();
if (className.endsWith(".class"))
{
className = className.substring(0, className.length() - ".class".length());
if (className.startsWith(packageName))
{
try
{
classes.add(Class.forName(className.replace('/', '.')));
} catch (ClassNotFoundException cnfe)
{
throw new CCException.Error("unable to find class named " + className.replace('/', '.') + "' within jar '" + jar + "'", cnfe);
}
}
}
}
private static void closeJarFile(final JarInputStream jarFile)
{
if(jarFile != null)
{
try
{
jarFile.close();
}
catch(IOException ioe)
{
mockAction();
}
}
}
他のヒント
おそらく最良のアプローチは、コンパイル時にクラスをリストすることです。
脆弱なランタイムアプローチがあります。 Class
(MyClass.class
of this.getClass()
)をご覧ください。 getProtectionDomain
を呼び出します。 getCodeSource
を呼び出します。 getLocation
を呼び出します。 openConnection
を呼び出します。 (または、リソースを開きます。)JarURLConnection
にキャストします。 getJarFile
を呼び出します。 entries
を呼び出します。 getName
のチェックを繰り返します。このアプローチは本当にお勧めしません。
JAR ファイルは名前が変更された ZIP ファイルであり、Javaで ZIP ファイルの内容を読むのは非常に簡単です。
File jarName = null;
try
{
jarName = new File (Dir.class.getProtectionDomain().getCodeSource().getLocation().toURI());
}
catch (Exception e)
{
e.printStackTrace();
}
try
{
ZipFile zf=new ZipFile(jarName.getAbsoluteFile());
Enumeration e=zf.entries();
while (e.hasMoreElements())
{
ZipEntry ze=(ZipEntry)e.nextElement();
System.out.println(ze.getName());
}
zf.close();
} catch (IOException e)
{
e.printStackTrace();
}
質問の10年後、仕事をする別の方法を提案します:
private static void listFilesFromDirectoryInsideAJar(String pathToJar,String directory,String extension) {
try {
JarFile jarFile = new JarFile(pathToJar);
Enumeration<JarEntry> e = jarFile.entries();
while (e.hasMoreElements()) {
JarEntry candidat = e.nextElement();
if (candidat.getName().startsWith(directory) &&
candidat.getName().endsWith(extension))
LOG.info(candidat.getName());
}
} catch (IOException e) {
LOG.error(e.getMessage(),e);
}
}
Javaはクラスのロード元のjarファイルへの直接アクセスを提供しないため、不可能です。 java.class.pathシステムプロパティを解析して検索することもできますが、すべての状況で機能するわけではありません。または、jarファイルの場所を制限したり、別の方法でクラスのリストを提供したりできます(マニフェストファイルなどを使用)。