【问题标题】:Opening PDF file stored in resources folder raises Exception打开存储在资源文件夹中的 PDF 文件引发异常
【发布时间】:2019-07-08 15:46:29
【问题描述】:

我编写了一个程序,其中应该在一个动作事件上打开一个 pdf 文件(您可以在下面查看我的代码)。

menuElementHilfe.addActionListener(new ActionListener() {   
    public void actionPerformed(ActionEvent arg0) {
        File hilfe = new File ("src\\resources\\Hilfe.pdf");
        try {
            java.awt.Desktop.getDesktop().open(hilfe);
        } catch (IOException e) {
            e.printStackTrace();
        }       
    }   
});

如果我通过 Eclipse 执行程序,一切正常,但在导出为可运行 jar 后,我得到以下异常:

线程“AWT-EventQueue-0”java.lang.IllegalArgumentException 中的异常:文件:src\resources\Hilfe.pdf 不存在。

感谢任何反馈

【问题讨论】:

    标签: java file resources


    【解决方案1】:

    您检索资源的方式可能是问题所在。试试这个:

    menuElementHilfe.addActionListener(new ActionListener() {   
        public void actionPerformed(ActionEvent arg0) {
        File hilfe = new File(getClass().getResource("/resources/Hilfe.pdf").getFile());
            try {
            java.awt.Desktop.getDesktop().open(hilfe);
            } catch (IOException e) {
                e.printStackTrace();
            }       
        }   
    });
    

    在 Eclipse 中运行时,您的目标是构建路径中的一个文件。 从 JAR/WAR 运行时,URL 不同,看起来像 "jar:file:/your-path/your-jar.jar!/Hilfe.pdf" 这不是您在调用时设置的new File(...) 因此,要获取内部资源的正确 URL,您必须根据需要使用 getResource 或 getResourceAsStream 等方法。

    查看以下说明以获取更多信息:) https://docs.oracle.com/javase/8/docs/technotes/guides/lang/resources.html

    [编辑]

    我假设您正在开发一些 Swing 应用程序,但我不知道您是否知道在 AWT-EventQueue 线程中执行类似的任务会冻结您的 UI。 为了防止你必须在另一个线程中运行与 UI 无关的东西。

    这是使用 SwingUtilities.invokeLater(Java 5 和更早版本)方法和/或 SwingWorker 类(自 Java 6 起)完成的。

    正如answer中提到的那样

    你应该把以前的解决方案放在这样的地方:

     SwingUtilities.invokeLater(new Runnable() {
        public void run() {
           // Your UI unrelated code here
        }
     });
    

    【讨论】:

      【解决方案2】:

      资源可以打包在应用程序jar中,因此是File(物理磁盘文件) 不可能。将其复制到一个临时文件中,以便桌面可以打开它。

      menuElementHilfe.addActionListener(evt -> {   
          Path tmp = Files.createTempFile("hilfe-", ".pdf");
          Files.copy(getClass().getResourceAsStream("/Hilfe.pdf"), tmp);
          try {
              Desktop.getDesktop().open(tmp.toFile());
              tmp.toFile().deleteOnExit();
          } catch (IOException e) {
              e.printStackTrace();
          }       
      });
      

      另一个区别是正斜杠,路径区分大小写,与 Windows 文件相反。


      问题后

      menuElementHilfe.addActionListener(evt ->
              SwingUtilities.invokeLater(() -> {
                  Path tmp = Files.createTempFile("hilfe-", ".pdf");
                  Logger.getLogger(getClass().getName()).log(Level.INFO, "actionPerformed "
                          + tmp + "; event: " + evt);
                  Files.copy(getClass().getResourceAsStream("/resources/Hilfe.pdf"), tmp);
                  try {
                      Desktop.getDesktop().open(tmp.toFile());
                      //tmp.toFile().deleteOnExit();
                  } catch (IOException e) {
                      Logger.getLogger(getClass().getName()).log(Level.WARN, "Error with " + tmp,
                              e);
                  }       
              }));
      
      • 我没有删除,所以Desktop 访问可以比java 应用更长寿。
      • 我做了一个invokeLater,以便在 actionPerformed 上没有冻结的 GUI。
      • 我添加了日志记录以查看每次调用 actionPerformed

      【讨论】:

      • 感谢您的回答,但我认为有些东西在这里不起作用。在 Desktop.getDesktop().open(hilfe.toFile());我得到错误:hilfe 无法解决
      • @Sven 应该有tmp 而不是hilfe(两次)。已更正
      • 表示在类路径(getResource/getResourceAsStream)上找不到路径。打开 jar(7zip 等),然后查找(区分大小写的)路径。也许应该是/resources/Hilfe.pdf/hilfe.PDF 或其他。
      • 7zip中的完整路径为 D:\Tool\tool.jar\resources\Hilfe.pdf ;我应该使用它而不是“/Hilfe.pdf”
      • 如果tool.jar在类路径中,包含类,路径应该是/resources/Hilfe.pdf
      猜你喜欢
      • 1970-01-01
      • 2014-08-25
      • 2013-12-06
      • 2018-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-02
      相关资源
      最近更新 更多