【问题标题】:read from a file that is in the same folder as the .jar file从与 .jar 文件位于同一文件夹中的文件读取
【发布时间】:2013-02-04 17:19:58
【问题描述】:

有没有办法读取与 .jar 文件位于同一文件夹中的文件?我正在尝试创建一个在提交作业时必须从文件中读取的 java 程序。一旦我把文件或程序翻过来,我不知道文件或程序将保存在哪里,所以我认为我不能对保存文件的目录进行编码。这可能吗?问题是我必须将文件上传到作为 linux 服务器的 CSX 主机服务器并从那里运行它。如果我不在文件前添加路径,它只会搜索其当前文件夹位置吗?

【问题讨论】:

  • 您的上下文是什么:Applet 还是桌面?你能把文件作为资源放入JAR吗?
  • 你能让你的程序把文件的路径作为命令行参数吗?
  • 使用 ClassLoader.findResource 查找您的课程。解码生成的 URL 以找出它的位置。
  • 为什么不在答案框中回答问题?
  • (当然,findResource 是受保护的,所以需要一些聪明才智。)

标签: java file jar


【解决方案1】:

您可以通过以下方式获取包含任何特定类的 JAR 文件的位置:

URL url = thisClass.getProtectionDomain().getCodeSource().getLocation();

从那里很容易将 URL 相对于所需的文件。

【讨论】:

    【解决方案2】:

    如 cmets 中所述,这仅在您从 jar 所在目录运行命令时才有效。

    (在桌面应用程序的上下文中)
    要访问位于jar 的当前目录中的文件,您对该文件的path 前面应该有一个点。示例:

    String path = "./properties.txt";
    FileInputStream fis = new FileInputStream(path);
    BufferedReader in = new BufferedReader(new InputStreamReader(fis));
    // Read the file contents...
    

    在此示例中,在与 jar 相同的目录中有一个名为 properties.txt 的文本文件。
    此文件将由 jar 中包含的程序读取。

    编辑:您说文件名不会更改,并且此答案适用于您事先知道名称的情况,当然,您是否更愿意对其进行硬编码。

    【讨论】:

    • 这是一个比我的解决方案更清洁的解决方案,但它不能处理所有情况。有时一个人的当前目录( . )与包含应用程序 jar 的目录不同。假设您的 jar 名为 app.jar 并且位于名为 target 的目录中;如果评分者从目标目录中键入“java -jar app.jar”,那么您的解决方案将起作用。但是,如果评分者要在应用程序目录之外运行一级 java 命令,例如"java -jar ./target/app.jar" 那么您的解决方案将在目标目录之外查找输入文件,因此找不到它。
    • 在文件名前面添加 './' 完全没有任何作用。 “JAR 的当前目录”与“与 .jar 相同的文件夹”不同。 -1
    • 对我来说,它似乎只在从终端运行 .jar 文件时工作。如果我试图用 Java Runtime 打开它,它就不起作用。当我想查看“。”的绝对路径时。文件它返回我的主文件夹位置。对我有用的是创建存储 .jar 文件父文件夹路径的字符串: String filesDirectory = (new File(getClass().getProtectionDomain().getCodeSource().getLocation().getPath()).getParent() + "/").replace("%20", ""); .无论如何,我会很感激一些更漂亮的解决方案。
    • @Bain 与删除它相比,它实际上什么也做不了。
    • 需要强调@Darwyn 评论。仅当命令在 JAR 目录中运行时才有效。
    【解决方案3】:

    如果输入文件名可以被硬编码,并且您知道它将始终与包含您的代码的 jar 位于同一目录中,那么这应该可以:

    public static void main(String[] args) {
    
        try {
            // Determine where the input file is; assuming it's in the same directory as the jar
            String fileName = "input.txt";
            File jarFile = new File(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
            String inputFilePath = jarFile.getParent() + File.separator + fileName;         
            FileInputStream inStream = new FileInputStream(new File(inputFilePath));
    
            try {
    
                // Read in the contents of the input file in a single gulp
                FileChannel fc = inStream.getChannel();
                MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0,
                        fc.size());
    
                // Do something with the read in data
                System.out.println(Charset.defaultCharset().decode(bb)
                        .toString());
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                inStream.close();
            }
    
        } catch (IOException | URISyntaxException e) {
            e.printStackTrace();
        }
    
    }
    

    【讨论】:

    • "这应该可以工作:" 它不能在 applet 或任何使用 JWS 启动的应用程序中工作,也可能不是 servlet。甚至 Sun 很久以前就告诉我们 WTE,“不要试图找到可执行文件 - 它与应用程序无关。业务”。
    • 是的,它会在 applet 中失败,或者在通过 java web start 启动时,或者在应用程序服务器(例如 OSGi、IBM WebSphere、Oracle WebLogics 等)中运行时失败。但它可以作为普通的桌面 java 应用程序运行。
    • 桌面应用程序。? “一个 linux 服务器并从那里运行它” 在我看来,这不像桌面。
    【解决方案4】:

    @kcpr - 感谢您提供的解决方案。下面一个对我有用。

    private static String CONFIG_FILE_LOCATION = "lib"+ File.separator + "Config.properties";
    
    static {
        File jarFile = new File(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
        String inputFilePath = jarFile.getParent() + File.separator + CONFIG_FILE_LOCATION; 
        propConfig = new PropertiesConfiguration(new File(inputFilePath));
        propConfig.load();
    }
    

    【讨论】:

    • 为什么需要toURI()getLocation() 返回一个似乎包含相同路径的 URL 对象...我错过了什么吗?
    【解决方案5】:

    要使其“独立”,请将资源放入 Jar。然后它变成一个(只读)embedded resource,我们可以使用以下内容获取一个 URL:

    URL url = this.getClass().getResource("/path/to/the.resource");
    

    【讨论】:

      【解决方案6】:

      以下是获取 jar 文件的干净目录路径的方法(基于 EJP 的回答):

      URL url = IssueInfoController.class.getProtectionDomain().getCodeSource().getLocation();
      String urlString = url.toString();
      int firstSlash =  urlString.indexOf("/");
      int targetSlash = urlString.lastIndexOf("/", urlString.length() - 2) + 1;
      
      return urlString.substring(firstSlash, targetSlash) + YOUR_FILE;
      

      【讨论】:

      • 应该使用URL.getPath() 而不是所有这些。
      【解决方案7】:

      根据您的 cmets,我认为您最好的解决方案是将上传文件的绝对路径传递到 jar 中。

      您可以将路径作为命令行参数传递到 jar 中。由于路径和文件名没有改变,并且您是从 linux 运行它,您可以创建一个 .sh 脚本来运行它。

      #!/bin/bash    
      java -jar myjar.jar /path/to/file/filename.txt
      

      这也使您无需在文件路径中进行硬编码,或将文件名放入 jar 中。

      【讨论】:

      • 不回答问题。再读一遍。他不知道文件会在哪里。
      • 真理不是时间的函数。
      【解决方案8】:
      public class TestClassLoaderAccess {
          public static void main(String[] argv) {
              TestClassLoaderAccess me = new TestClassLoaderAccess();
              ClassLoader myLoader = me.getClass().getClassLoader();
              System.out.println(myLoader.getClass().getSuperclass().getName());
              java.net.URLClassLoader myUrlLoader = (java.net.URLClassLoader) myLoader;
              java.net.URL resource = myUrlLoader.findResource("TestClassLoaderAccess.class");
              System.out.println(resource.toString());
          }
      }
      

      运行它:

      C:\JavaTools>javac TestClassLoaderAccess.java
      
      C:\JavaTools>java TestClassLoaderAccess
      java.net.URLClassLoader
      file:/C:/JavaTools/TestClassLoaderAccess.class
      
      C:\JavaTools>
      

      (第一个println只是为了证明类加载器是URLClassLoader的子类。)

      【讨论】:

      • 这会在 JAR inside 中找到资源。它只在这里有效,因为根本没有 JAR。不是要求的。没有答案。
      猜你喜欢
      • 2015-11-23
      • 2011-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-14
      相关资源
      最近更新 更多