【问题标题】:How to read a file that is located in any location on the computer?如何读取位于计算机上任何位置的文件?
【发布时间】:2020-06-23 16:13:37
【问题描述】:

所以我有一个项目,这是需求之一:

     You should have a class named Project3, containing a main method.
 This program reads the levels information from a file whose name is
specified as a command-line parameter  (The file should also be
 relative to the class-path as described here:)

关卡和块定义文件中指定的所有文件名 应该相对于类路径。我们希望他们成为的原因 相对于类路径的是,稍后我们将能够读取 jar 中的文件,这是我们无法使用常规文件执行的操作 参考文献。

获取一个相对于类路径的输入流(即使它在里面 一个罐子),使用以下内容:

输入流是 = ClassLoader.getSystemClassLoader().getResourceAsStream("image.png"); 这个想法是保留一个包含文件(定义和图像)的文件夹和 然后在运行 JVM 时将该文件夹添加到类路径中:

java -cp bin:resources ... 如果不添加资源文件夹 您的类路径将无法使用以下命令加载它们 以上。

 When run without parameters, your program should read a default level
 file, and run the game accordingly. The location of the default level
 file should be hard-coded in your code, and be relative to the
 classpath_.

当不带参数运行时,你的程序应该读取一个默认的关卡文件,并相应地运行游戏。默认关卡文件的位置应该在你的代码中硬编码,并且是相对于classpath_的。

处理输入的部分代码是:

  public Void run() throws IOException {
    LevelReader level = new LevelReader();
    List<level> chosenLevels = new ArrayList<>();
        if (args.length >= 1) {
            File f = new File(args[0]);
            if (f.exists()) {
                        chosenLevels = level.makeLevel(args[0]);
                    }
        }
    if (chosenLevels.size() == 0) {
        game.runLevels(defaultLevels);
    } else {
        game.runLevels(chosenLevels);
    }
    return null;
}

所以我的问题是:

  • 参数应该是文件的完整路径,这意味着: D:\desktop\level3.txt

    是否可以从我计算机上的每个位置读取文件? 因为现在我只能在我的文本文件位于 项目的目录(甚至不在 src 文件夹中)。

  • 我无法理解他们的其他要求。什么是“应该在你的代码中硬编码,并且相对于 classpath_." 以及为什么它与 InputStream 方法有关(?)

我对此感到困惑。 谢谢。

【问题讨论】:

标签: java parsing text


【解决方案1】:

类路径资源与文件不同。

正如您所说的,文件的完整路径类似于D:\desktop\level3.txt

但是,如果想要分发您的应用程序以便它可以在其他计算机上运行,​​而其他计算机可能在该位置没有该文件,您有两个选择:

  • 要求用户告诉程序在他们的计算机上哪里可以找到文件。
  • 将文件与已编译的程序捆绑在一起。

如果您将非 .class 文件与 .class 文件放在同一位置,则将其视为资源。由于您在运行时不知道程序的类文件所在的位置¹,因此您使用 getResourcegetResourceAsStream 方法,该方法专门用于查看类路径。

getResource* 方法还有一个额外的好处,即它们在您进行开发以及将程序打包为 .jar 文件时都可以使用。 .jar 文件中的各个条目不是单独的文件,无法使用 FileFileInputStream 类读取。

如果我正确理解您的分配,默认级别文件应该是应用程序资源,并且该资源的名称应该是在您的程序中硬编码的内容。比如:

InputStream is;
if (args.length > 0) {
    is = new BufferedInputStream(
        new FileInputStream(args[0]));
} else {
    // No argument provided, so use program's default level data.
    is = ClassLoader.getSystemClassLoader().getResourceAsStream("defaultlevel.txt");
}

chosenLevels = level.makeLevel(is);

¹您可能会发现一些页面声称您可以使用 getProtectionDomain().getCodeSource() 确定正在运行的程序代码的位置,但 getCodeSource() 可能会返回 null,具体取决于 JVM 和 ClassLoader 实现,因此这是不可靠的。

【讨论】:

  • 我的程序在 intellij 上运行正常,但是当我尝试从 jar 运行它时它不起作用。它确实运行文本文件,但不运行其中的 jpg 文件。
  • “里面的 jpg 文件”是什么意思?图像数据是否在文本文件中?或者你在文本文件中有一个文件名?显然,文件的路径在其他计算机上无效。如果图像是程序的一部分,那么它也应该是应用程序资源,并且文本文件应该使用相对于类路径根目录的资源路径而不是文件名来引用图像。
  • 我在一个类中有一个函数,它执行以下操作: InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream(backgrounds/bg.jpg); this.image = ImageIO.read(is); ///// 这带来了 null 并且程序无法“找到”或获取访问权限,或者我不知道该图像是什么。这不是代码问题,因为它在 inellij 中运行良好。只有当我将它编译成jar文件时,它才不起作用。
  • 检查 .jar 文件的内容。它里面有backgrounds/bg.jpg 条目吗? (您应该能够使用 IDE 检查 .jar 文件。如果这不起作用,请复制 .jar 文件并将副本的扩展名更改为 .zip,然后使用任何 zip 工具打开它。)
【解决方案2】:

要回答您的第一个问题,他们似乎并没有要求您从磁盘上的任何位置读取,只是从您的类路径中读取。所以看起来不错。

第二个问题,“'应该在代码中硬编码,并且与类路径相关'是什么意思?”。你的项目目录中总是会有一个默认的关卡文件。在您的程序中将此文件的路径定义为字符串,并且该要求将得到满足。它与 InputStream 相关,因为流需要从位置读取。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-20
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 2017-04-20
    • 1970-01-01
    • 2021-11-03
    相关资源
    最近更新 更多