是否可以在 .jar 中获取 class 包的目录?
Is it possible to get the directory of a class package within a .jar?
我正在尝试将 class 包的目录作为我的 .jar 中的 File
(层次结构为 /controller/core
):
File directory_file_of_package = new File(getClass().getResource("/controller/core").toURI());
当我 运行 IDE 中的程序时有效,但是当我 运行 它作为独立的 .jar 时,它给我这个错误:
java.lang.IllegalArgumentException: URI is not hierarchical
查看这些问题 (why my URI is not hierarchical? and Java Jar file: use resource errors: URI is not hierarchical) 对我没有帮助,因为这些问题涉及在 .jar 中获取 File
作为资源 (getResourceAsStream()
),但我我正在尝试获取一个目录。
此外,接受的答案指出:
Generally the IDEs separates on file system classes and resources. But when the jar is created they are put all together.
那么,是不是就没有办法抓取/controller/core
的目录了?
我的 XY 问题:
我正在尝试使用 CSVJDBC (http://csvjdbc.sourceforge.net/) 读取 .CSV 文件,DriverManager
引用 CSV 文件的方式就好像 包含文件夹是数据库和CSV文件 是 table.
public class SearchData {
void SearchData() {
try {
Class.forName("org.relique.jdbc.csv.CsvDriver");
File directory_file_of_package_containing_csv = new File(getClass().getResource("/controller/core").toURI());
// Driver points to directory which contains the CSV file as if it is the database
Connection conn = DriverManager.getConnection("jdbc:relique:csv:" + directory_file_of_package_containing_csv.toString());
System.out.println("Connection established.");
Statement stmt = conn.createStatement();
System.out.println("Statement created.");
// CSV is named "data.csv" so the CsvDriver sees "data" as the table name
String sql = "SELECT id,name FROM data";
ResultSet results = stmt.executeQuery(sql);
...
} catch (ClassNotFoundException | SQLException | URISyntaxException e) {
e.printStackTrace();
}
}
}
如何将 CsvJdbc 指向包含在 .jar 中的 csv 文件?
JAR 中根本没有包的目录。它在 IDE 中工作,因为您的 class 尚未打包到 JAR 文件中并且驻留在某个目录中。但 JAR 不是这种情况。
因此,如果您使用的某些库需要一个包含文件的目录,您通常无法使用 classpath 资源实现此目的。其中一种选择是在临时目录中创建一份资源副本作为文件。
或者你可能想进一步研究 CsvJDBC documentation:
To read data that is either held inside the Java application (for example, in a JAR file) or accessed remotely (for example, using HTTP requests), create a Java class that implements the interface org.relique.io.TableReader
and give this class name in the connection URL. CsvJdbc then creates an instance of this class and calls the getReader
method to obtain a java.io.Reader
for each database table being read.
所以你应该能够在没有临时目录的情况下为 CsvJDBC 解决这个问题。
我正在尝试将 class 包的目录作为我的 .jar 中的 File
(层次结构为 /controller/core
):
File directory_file_of_package = new File(getClass().getResource("/controller/core").toURI());
当我 运行 IDE 中的程序时有效,但是当我 运行 它作为独立的 .jar 时,它给我这个错误:
java.lang.IllegalArgumentException: URI is not hierarchical
查看这些问题 (why my URI is not hierarchical? and Java Jar file: use resource errors: URI is not hierarchical) 对我没有帮助,因为这些问题涉及在 .jar 中获取 File
作为资源 (getResourceAsStream()
),但我我正在尝试获取一个目录。
此外,接受的答案指出:
Generally the IDEs separates on file system classes and resources. But when the jar is created they are put all together.
那么,是不是就没有办法抓取/controller/core
的目录了?
我的 XY 问题:
我正在尝试使用 CSVJDBC (http://csvjdbc.sourceforge.net/) 读取 .CSV 文件,DriverManager
引用 CSV 文件的方式就好像 包含文件夹是数据库和CSV文件 是 table.
public class SearchData {
void SearchData() {
try {
Class.forName("org.relique.jdbc.csv.CsvDriver");
File directory_file_of_package_containing_csv = new File(getClass().getResource("/controller/core").toURI());
// Driver points to directory which contains the CSV file as if it is the database
Connection conn = DriverManager.getConnection("jdbc:relique:csv:" + directory_file_of_package_containing_csv.toString());
System.out.println("Connection established.");
Statement stmt = conn.createStatement();
System.out.println("Statement created.");
// CSV is named "data.csv" so the CsvDriver sees "data" as the table name
String sql = "SELECT id,name FROM data";
ResultSet results = stmt.executeQuery(sql);
...
} catch (ClassNotFoundException | SQLException | URISyntaxException e) {
e.printStackTrace();
}
}
}
如何将 CsvJdbc 指向包含在 .jar 中的 csv 文件?
JAR 中根本没有包的目录。它在 IDE 中工作,因为您的 class 尚未打包到 JAR 文件中并且驻留在某个目录中。但 JAR 不是这种情况。
因此,如果您使用的某些库需要一个包含文件的目录,您通常无法使用 classpath 资源实现此目的。其中一种选择是在临时目录中创建一份资源副本作为文件。
或者你可能想进一步研究 CsvJDBC documentation:
To read data that is either held inside the Java application (for example, in a JAR file) or accessed remotely (for example, using HTTP requests), create a Java class that implements the interface
org.relique.io.TableReader
and give this class name in the connection URL. CsvJdbc then creates an instance of this class and calls thegetReader
method to obtain ajava.io.Reader
for each database table being read.
所以你应该能够在没有临时目录的情况下为 CsvJDBC 解决这个问题。