从JAR文件运行应用程序时出现URI不是分层结构异常

4

我已经将我的Java控制台应用程序导出为Jar文件,但是当我运行该jar并调用解析JSON文件的代码时,会出现java.lang.IllegalArgumentException异常。

有人知道为什么在作为JAR运行程序时会抛出异常吗?当应用程序从Eclipse运行时,解析工作正常。

当我执行jar文件并调用解析JSON文件的代码时,会输出以下确切错误:

Exception in thread "main" java.lang.IllegalArgumentException: URI is not hierar
chical
        at java.io.File.<init>(Unknown Source)
        at gmit.GameParser.parse(GameParser.java:44)
        at gmit.Main.main(Main.java:28)

这是我的GameParser类中解析的方式:
public class GameParser {
    private static final String GAME_FILE = "/resources/game.json";
    private URL sourceURL = getClass().getResource(GAME_FILE); 
    private int locationId;

    private List<Location> locations;
    private List<Item> items;
    private List<Character> characters;

    public void parse() throws IOException, URISyntaxException {
        ObjectMapper mapper = new ObjectMapper();
       mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        try {                   
            // read from file, convert it to Location class
            Location loc = new Location();
            loc = mapper.readValue(new File(sourceURL.toURI()), Location.class);
            Item item = mapper.readValue(new File(sourceURL.toURI()), Item.class);
            GameCharacter character = mapper.readValue(new File(sourceURL.toURI()), GameCharacter.class);

            // display to console
            System.out.println(loc.toString());
            System.out.println(item.toString());
            System.out.println(character.toString());
        } catch (JsonGenerationException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

这是我项目的文件夹结构: 源代码树
2个回答

8
调用 getClass().getResource(GAME_FILE); 将返回相对于 this 类的 URL。如果您从 JAR 文件中执行程序,它将返回指向 JAR 文件的 URL。 在 Java 中,文件只能表示直接的文件系统文件,而不能表示 zip/jar 归档文件中的文件。 为了解决这个问题:
  1. 尝试使用 getClass().getResourceAsStream() 并使用它代替 Files 或者
  2. 将文件提取到某个目录中,并像您现在尝试的那样使用 File

好的,那么在这种情况下的解决方法是什么?放弃使用getResource吗?你能展示一个代码片段的例子吗? - Brian Var
更新了提案。 - Crazyjavahacking
1
好的,我已经在上面添加了我的源代码树的快照。我尝试了上面的方法,但是File需要一个字符串而不是一个输入流。private InputStream sourceURL = getClass().getResourceAsStream(GAME_FILE);loc = mapper.readValue(new File(sourceURL), Location.class); - Brian Var
http://jackson.codehaus.org/1.8.8/javadoc/org/codehaus/jackson/map/ObjectMapper.html - Brian Var
那么我已经回答了你的问题,使用 readValue(sourceInputStream, Location.class) - Crazyjavahacking
好的,我现在明白了,所以我需要有:GameState parser = mapper.readValue(resourceAsStream, GameState.class);但是这将引发映射异常,http://hastebin.com/tolehexumi.avrasm。 - Brian Var

0
当你的项目中有一个名为“Images”的文件夹,同时你的桌面上也有另一个名为“images”的文件夹时,这个问题就会出现。自动地,JVM 选取桌面上的文件夹,如果你想确认,可以尝试打印你的 URI。在创建文件之前,使用这个示例来显示你的 URI。
try {
    URL location = this.getClass().getResource("/WavFile");
    System.out.println(location.toURI());
     File file = new File(location.toURI()); 
     if (!file.exists()) {
        System.out.println(file.mkdirs());
        System.out.println(file.getAbsoluteFile());
    }else
    {
         System.out.println(file.getPath());
    }
} catch (Exception e) {
    e.printStackTrace();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接