Java 读取jar中的文件

Java 读取jar中的文件,java,Java,我正试图打开我的jar档案中的一个文件 我使用这个Maven插件: <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.0.0</version> <configuration> <

我正试图打开我的jar档案中的一个文件

我使用这个Maven插件:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>3.0.0</version>
    <configuration>
      <archive>
        <manifest>
          <addClasspath>true</addClasspath>
          <mainClass>com.fatec.migration.script.utils.Script</mainClass>
        </manifest>
      </archive>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
    </configuration>
    <executions>
      <execution>
        <id>assemble-all</id>
        <phase>package</phase>
        <goals>
          <goal>single</goal>
        </goals>
      </execution>
    </executions>
  </plugin>
现在我可以试着运行它:

java -jar fatec-script-jar-with-dependencies.jar 1 2017-02-01 2017-02-02 all
唉,它找不到文件:

The file secure/extrapack-renew.sql could not be opened.
java.lang.NullPointerException
    at com.fatec.migration.script.utils.AbstractScript.loadSqlStatement(AbstractScript.java:75)
protected String loadSqlStatement(String scriptPath, String filename) {
    String filepath = buildSqlFilePath(scriptPath, filename);
    try {
        return new String(Files.readAllBytes(Paths.get(getClass().getResource(filepath).toURI())));
    } catch (Exception e) {
        System.err.println("The file " + filepath + " could not be opened.");
        e.printStackTrace();
    }
    return null;
}

private String buildSqlFilePath(String scriptPath, String filename) {
    return scriptPath + "/" + filename;
}    
但该文件确实存在,我可以在存档中看到它:

$ jar -tvf target/fatec-script-jar-with-dependencies.jar | grep "secure/extrapack-renew.sql"
  1844 Fri Feb 10 17:43:46 CET 2017 secure/extrapack-renew.sql
以下是我如何尝试打开文件:

The file secure/extrapack-renew.sql could not be opened.
java.lang.NullPointerException
    at com.fatec.migration.script.utils.AbstractScript.loadSqlStatement(AbstractScript.java:75)
protected String loadSqlStatement(String scriptPath, String filename) {
    String filepath = buildSqlFilePath(scriptPath, filename);
    try {
        return new String(Files.readAllBytes(Paths.get(getClass().getResource(filepath).toURI())));
    } catch (Exception e) {
        System.err.println("The file " + filepath + " could not be opened.");
        e.printStackTrace();
    }
    return null;
}

private String buildSqlFilePath(String scriptPath, String filename) {
    return scriptPath + "/" + filename;
}    
脚本路径为“安全”,文件名为“extrapack renew.sql”


我遗漏了什么?

我认为你的问题在于你使用
getResource()
的方式:

使用相对类路径(相对于当前类位置)检索
“extrapack renew.sql”
文件。
这意味着此资源必须位于jar中的此路径内才能检索。

如果资源不位于当前类路径内,则用于检索资源的路径应以
“/”
字符开头,以便指定资源的绝对名称:

Paths.get(getClass().getResource("/"+filepath).toURI());
当然,如果您使用maven,
extracack renew.sql
应该在


源项目的
src/main/resources/secure
文件夹,以便
“/secure/extrapack renew.sql”
成为类路径中的一个资源。

我的解决方案是让属性文件不在jar归档中,这与问题的原始标题中提出的问题相反

我用项目主目录中的一个属性文件使它工作

$ ll
total 52K
-rw-rw-r-- 1 stephane   10 févr. 13 10:49 application.properties
-rw-r--r-- 1 stephane 6,1K févr. 10 17:22 pom.xml
我可以打开此文件并加载其属性:

properties.load(new FileInputStream(new File(DB_AUTOSELF_PROPERTIES_FILENAME)));
然后我可以将
.jar
存档和属性文件移动到另一个目录,并运行应用程序:

$ pwd
/home/stephane/trash
$ cp ~/dev/java/projects/AS/target/script-jar-with-dependencies.jar .
$ cp ~/dev/java/projects/AS/application.properties .
$ vi application.properties 
-rw-rw-r-- 1 stephane 10 févr. 13 10:53 application.properties
java -jar script-jar-with-dependencies.jar 1 2016-12-01 2017-02-12 all
我的
pom.xml
文件包含用于复制资源和创建fat
jar
存档的插件:

  <plugin>
    <artifactId>maven-resources-plugin</artifactId>
    <executions>
      <execution>
        <id>copy-resources</id>
        <phase>validate</phase>
        <goals>
          <goal>copy-resources</goal>
        </goals>
        <configuration>
          <outputDirectory>${basedir}/target</outputDirectory>
          <resources>
            <resource>
              <directory>src/main/resources</directory>
              <filtering>true</filtering>
            </resource>
          </resources>
        </configuration>
      </execution>
    </executions>
  </plugin>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>3.0.0</version>
    <configuration>
      <archive>
        <manifest>
          <addClasspath>true</addClasspath>
          <mainClass>com.fatec.migration.script.utils.Script</mainClass>
        </manifest>
      </archive>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
    </configuration>
    <executions>
      <execution>
        <id>assemble-all</id>
        <phase>package</phase>
        <goals>
          <goal>single</goal>
        </goals>
      </execution>
    </executions>
  </plugin>

maven资源插件
复制资源
验证
复制资源
${basedir}/目标
src/main/resources
真的
org.apache.maven.plugins
maven汇编插件
3.0.0
真的
com.fatec.migration.script.utils.script
带有依赖项的jar
集合所有
包裹
单一的

SQL文件在jar文件中。它不应该被移动或改变。假设它是硬编码的。也许我不需要把它放在外部文件中,更不用说放在资源文件中了。事实上,如果你不需要在打包jar后更改它,你就没有义务将文件从jar中移出。这是一种部署选择。