我有一個用例,我需要將這段代碼導出爲一個Java庫(最終將成爲JAR),但問題在於它需要使用一段信息存儲在文件系統上的物理文件中。內部JAR使用文件系統上的文件
我有2個問題在這裏:
1)我應該在哪裏穿上,我能想到的是在包含庫中的Java模塊的資源目錄中的文件系統(一種選擇這些文件:有一個疑問,雖然資源目錄是否也被編譯到jar中?)
2)當我從外部Java應用程序使用該庫時,庫如何能夠找到這些文件?他們仍然會在類路徑中嗎?
我有一個用例,我需要將這段代碼導出爲一個Java庫(最終將成爲JAR),但問題在於它需要使用一段信息存儲在文件系統上的物理文件中。內部JAR使用文件系統上的文件
我有2個問題在這裏:
1)我應該在哪裏穿上,我能想到的是在包含庫中的Java模塊的資源目錄中的文件系統(一種選擇這些文件:有一個疑問,雖然資源目錄是否也被編譯到jar中?)
2)當我從外部Java應用程序使用該庫時,庫如何能夠找到這些文件?他們仍然會在類路徑中嗎?
我發現了一個相關的答案的另一個問題的一部分:How to load a folder from a .jar?
我可以使用下面的代碼成功地檢索文件:
/**
* List directory contents for a resource folder. Not recursive.
* This is basically a brute-force implementation.
* Works for regular files and also JARs.
*
* @author Greg Briggs
* @param clazz Any java class that lives in the same place as the resources you want.
* @param path Should end with "/", but not start with one.
* @return Just the name of each member item, not the full paths.
* @throws URISyntaxException
* @throws IOException
*/
String[] getResourceListing(Class clazz, String path) throws URISyntaxException, IOException {
URL dirURL = clazz.getClassLoader().getResource(path);
if (dirURL != null && dirURL.getProtocol().equals("file")) {
/* A file path: easy enough */
return new File(dirURL.toURI()).list();
}
if (dirURL == null) {
/*
* In case of a jar file, we can't actually find a directory.
* Have to assume the same jar as clazz.
*/
String me = clazz.getName().replace(".", "/")+".class";
dirURL = clazz.getClassLoader().getResource(me);
}
if (dirURL.getProtocol().equals("jar")) {
/* A JAR path */
String jarPath = dirURL.getPath().substring(5, dirURL.getPath().indexOf("!")); //strip out only the JAR file
JarFile jar = new JarFile(URLDecoder.decode(jarPath, "UTF-8"));
Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
Set<String> result = new HashSet<String>(); //avoid duplicates in case it is a subdirectory
while(entries.hasMoreElements()) {
String name = entries.nextElement().getName();
if (name.startsWith(path)) { //filter according to the path
String entry = name.substring(path.length());
int checkSubdir = entry.indexOf("/");
if (checkSubdir >= 0) {
// if it is a subdirectory, we just return the directory name
entry = entry.substring(0, checkSubdir);
}
result.add(entry);
}
}
return result.toArray(new String[result.size()]);
}
throw new UnsupportedOperationException("Cannot list files for URL "+dirURL);
}
您可以傳遞屬性文件中的文件位置或某種技術。
我應該在哪裏放於文件系統
這是由你來決定,雖然這將是一個好主意,使這個配置這些文件。嘗試適應主機操作系統/發行版的慣例也是一個好主意,雖然這些會有所不同......並取決於應用程序的性質。
當我從外部Java應用程序使用此庫時,庫如何能夠找到這些文件?
您通常會使用配置屬性或初始化參數來保存/傳遞位置。如果你正在編寫一個應用程序而不是一個庫,那麼你可以使用Java Preferences APIs,儘管這對圖書館來說可能是一個糟糕的選擇。
它們仍然在類路徑中嗎?
只有當你將該位置放在classpath上...並且這會使配置更加棘手。鑑於這些文件需要存儲在文件系統中,我建議使用FileInputStream
或類似的文件。
@ StephenC-I已經有我的文件。我想知道一種將這些文件打包到jar本身的方法,這樣使用jar的獨立應用程序就不必關心這些文件。爲了讓問題更清楚一些,我想確認一下,當這些文件是jar的一部分並被同一個jar中的類引用時,這個jar被其他幾個應用程序使用,引用是否相同因爲我們將訪問模塊中的普通資源文件?我的意思是,從應用程序的角度來看,classpath是否也有這些文件? –
使用Eclipse,我總是創建一個包'資源',在那裏放置jar需要的文件。我通過
this.getClass().getClassLoader().getResources("/resources/file.ext");
訪問文件(從幾乎任何地方)隨着導出 - >運行的JAR所有這些文件都包含在該.jar。我不確定這是否是正確的做法。另外,我對資源之前的「/」不是100%確定的,也許應該省略。
OP提到了Eclipse嗎?他實際上正在討論將獨立於Eclipse安裝的應用程序/庫。 –
你有兩個選擇,第一個是將文件放在包結構中,這樣它們將被打包在jar中。
getClass().getResourceAsStream("/path/to/your/resource/resource.ext");
如果你想從一個名爲A,則類的靜態方法來調用它,你應該這樣寫:
A.class.getResourceAsStream("/path/to/your/resource/resource.ext");
的「/路徑」的一部分,你會從這樣的代碼讓他們的路徑是最頂層的包,而resource.ext是您的文件名。
另一種選擇是把他們的jar包之外,但隨後的罐子需要知道自己的位置:
我undestood你queastion並回答它的方式文件的位置,它無關classpath:
CLASSPATH變量是一種告訴應用程序(包括JDK工具)在哪裏查找用戶類的方法。 (類屬於JRE,JDK平臺的一部分,並擴展應該通過其他方式來定義,比如引導類路徑或擴展目錄。)
編輯: ,但你仍然可以,把它放在那裏並從這樣的代碼得到它:
System.getProperty("java.class.path");
然而它會需要一些邏輯來解析它。
能有什麼文件呢?配置文件?該文件是否應該被覆蓋? –
目前還不清楚您是否想用JAR移動文件(使用'getResourceAsStream'),或者文件獨立於JAR(指定用戶可編輯的.properties中的路徑/將其作爲啓動參數傳遞,通過註銷來回答) – SJuan76
@ Pierre-HenriToussaint - 是的,你可以把它當作一個配置文件,但是我想問的一點是:讓我們把它的範圍擴展到我需要暴露給各種應用程序的類。這些類需要訪問這些配置文件(並且這些類是獨立於使用類的應用程序而固定的)。當這個jar被導入到應用程序,並且應用程序嘗試使用上面提到的jar中的一個類來嘗試從配置文件中檢索一些信息時,是否所有東西都能正常工作,沒有任何類路徑問題? –