JAR内の特定のディレクトリに格納された定義ファイルをすべて読み込む
やりたいこと
JAR内の特定のディレクトリに格納された定義ファイルをすべて読み込みたい。
例えばJARの構成が以下であった場合、messagesディレクトリに格納された*.propertiesを読み込みます。
xxx.jar ├META-INF/ | └MANIFEST.MF ├com/ | └example/ | └Test.class └messages/ ├a.properties └b.properties
実装
クラスパス上のリソースファイルを読み込むためには一般的にgetResourceAsStreamを使いますが、JAR内の場合はひと工夫必要らしいです。
package jp.gr.java_conf.ksino.readmessages; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.util.Enumeration; import java.util.jar.JarEntry; import java.util.jar.JarFile; /** * * @author ksino */ public class Main { private static final String MESSAGES_DIR = "messages/"; public static void main(String[] args) throws IOException { loadMessages(); } private static void loadMessages() { ClassLoader classLoader = Main.class.getClassLoader(); URL url = classLoader.getResource(MESSAGES_DIR); if (url == null) { // 例外処理 } else { if (url.getProtocol().equals("jar")) { // 定義ファイルがJAR内の場合 String[] s = url.getPath().split(":"); String path = s[s.length - 1].split("!")[0]; File f = new File(path); JarFile jarFile; try { jarFile = new JarFile(f); Enumeration<JarEntry> entries = jarFile.entries(); while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); String name = entry.getName(); if (name != null && name.startsWith(MESSAGES_DIR)) { try (InputStream is = classLoader.getResourceAsStream(name);) { read(is); } } } } catch (IOException ex) { //例外処理 } } else { // 定義ファイルがJAR外の場合 File dir = new File(url.getPath()); String[] fileNames = dir.list(); for (String fileName : fileNames) { try (InputStream is = classLoader.getResourceAsStream(MESSAGES_DIR + fileName);) { read(is); } catch (IOException ex) { // 例外処理 } } } } } private static void read(InputStream is) { try (InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr);) { // 読み込み処理はちゃんと書く。。。 String line = null; while ((line = br.readLine()) != null) { System.out.println(line); } } catch (IOException ex) { // 例外処理 } } }
動作確認に使用したリソース
JARの構成
ReadMessagesInClasspath.jar ├META-INF/ | └MANIFEST.MF ├jp/ | └gr/ | └java_conf/ | └ksino/ | └readmessages/ | └Main.class └messages/ ├a.properties └b.properties
a.properties
aaa=bbb ccc=ddd
b.properties
zzz=xxx yyy=vvv www=123
動作確認結果
$ java -cp ReadMessagesInClasspath.jar jp.gr.java_conf.ksino.readmessages.Main aaa=bbb ccc=ddd zzz=xxx yyy=vvv www=123