Java如何解析新File()中的相对路径?

时间:2014-01-11 10:08:02

标签: java file relative-path

我试图了解Java在创建File对象时解析相对路径的方式。

使用的操作系统:Windows

对于以下代码段,我收到IOException,因为它无法找到路径:

@Test
public void testPathConversion() {
        File f = new File("test/test.txt");
        try {
            f.createNewFile();
            System.out.println(f.getPath());
            System.out.println(f.getAbsolutePath());    
            System.out.println(f.getCanonicalPath());
        } catch (Exception e) {
            e.printStackTrace();
        }
}

我的理解是,Java将提供的路径视为绝对路径,并在路径不存在时返回错误。所以这很有道理。

当我更新上面的代码以使用相对路径时:

@Test
    public void testPathConversion() {
        File f = new File("test/../test.txt");
        try {
            f.createNewFile();
            System.out.println(f.getPath());
            System.out.println(f.getAbsolutePath());    
            System.out.println(f.getCanonicalPath());
        } catch (Exception e) {
            e.printStackTrace();
        }    
    }

它会创建一个新文件并提供以下输出:

test\..\test.txt
C:\JavaForTesters\test\..\test.txt
C:\JavaForTesters\test.txt

在这种情况下,我的假设是,即使提供的路径不存在,因为路径包含“/../”,java将其视为相对路径并在user.dir中创建文件。所以这也是有道理的。

但如果我更新相对路径如下:

   @Test
    public void testPathConversion() {
        File f = new File("test/../../test.txt");
        try {
            f.createNewFile();
            System.out.println(f.getPath());
            System.out.println(f.getAbsolutePath());
            System.out.println(f.getCanonicalPath());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

然后我得到IOException:访问被拒绝。

我的问题是:

  1. 为什么"test/../test.txt"被视为相对路径并在"user.dir"中创建文件,但"test/../../test.txt"会返回错误?它在哪里尝试为路径"test/../../test.txt"创建文件?
  2. 当找不到指定的相对路径时,该文件似乎是在user.dir中创建的。所以,在我看来,下面两个场景做了同样的事情:

    //scenario 1
    File f = new File("test/../test.txt");
    f.createNewFile();
    
    //scenario 2
    File f = new File("test.txt");
    f.createNewFile();
    
  3. 那么有一个真实世界的情况,人们会使用场景1而不是场景2吗?

    我想我错过了一些明显的东西,或者从根本上误解了相对路径。我浏览了文档的Java文档,但我无法找到解释。 Stack Overflow中有很多关于相对路径的问题,但我查找的是针对特定场景而不是关于如何解析相对路径的问题。

    如果有人可以解释一下这是如何运作的,或者指向某些相关链接,那将会很棒吗?

6 个答案:

答案 0 :(得分:20)

working directory的概念 该目录由.(点)表示 在相对路径中,其他一切都与它相关。

只需将.(工作目录)放在运行程序的位置即可。
在某些情况下,工作目录可以更改,但通常这是
点代表什么。我认为这是C:\JavaForTesters\

所以test\..\test.txt表示:子目录test
在我的工作目录中,然后一级,然后是 档案test.txt。这与test.txt基本相同。

有关详情,请点击此处。

http://docs.oracle.com/javase/7/docs/api/java/io/File.html

http://docs.oracle.com/javase/tutorial/essential/io/pathOps.html

答案 1 :(得分:9)

当您的路径以根目录开头,即Windows中的C:\或Unix中的/或java资源路径中的路径时,它被视为绝对路径。其他一切都是相对的,所以

new File("test.txt") is the same as new File("./test.txt")

new File("test/../test.txt") is the same as new File("./test/../test.txt")

getAbsolutePathgetCanonicalPath之间的主要区别在于,第一个连接父路径和子路径,因此它可能包含点:...getCanonicalPath将始终为特定文件返回相同的路径。

注意:File.equals使用路径的抽象形式(getAbsolutePath)来比较文件,这意味着相同的两个File对象可能不相等而{{1}在FileMap等集合中使用是不安全的。

答案 2 :(得分:5)

工作目录是几乎所有操作系统和程序语言等的通用概念。它是程序运行的目录。这通常(但并非总是如此,有更改方法)应用程序所在的目录。

相对路径是在没有驱动器说明符的情况下启动的路径。所以在Linux中,它们不是以/开头,在Windows中它们不是以C:\开头等等。这些始终从您的工作目录开始。

绝对路径是以驱动器(或网络路径的机器)说明符开头的路径。它们总是从那个驱动器开始。

答案 3 :(得分:1)

如果您了解Java如何运行程序,则可以最好地理解相对路径。

在Java中运行程序时,有一个工作目录的概念。假设您有一个类,比如,/User/home/Desktop/projectRoot/src/topLevelPackage/执行IO java

根据您调用projectRoot来运行程序的情况,您将拥有不同的工作目录。如果从内部和IDE运行程序,它很可能是$ projectRoot/src : java topLevelPackage.FileHelper

  • 在这种情况下src它将是$ projectRoot : java -cp src topLevelPackage.FileHelper

  • 在这种情况下projectRoot它将是$ /User/home/Desktop : java -cp ./projectRoot/src topLevelPackage.FileHelper

  • 在这种情况下Desktop它将是(Assuming $ is your command prompt with standard Unix-like FileSystem. Similar correspondence/parallels with Windows system)

(.)

因此,您的相对路径根package topLevelPackage import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; public class FileHelper { // Not full implementation, just barebone stub for path public void createLocalFile() { // Explicitly get hold of working directory String workingDir = System.getProperty("user.dir"); Path filePath = Paths.get(workingDir+File.separator+"sampleFile.txt"); // In case we need specific path, traverse that path, rather using . or .. Path pathToProjectRoot = Paths.get(System.getProperty("user.home"), "Desktop", "projectRoot"); System.out.println(filePath); System.out.println(pathToProjectRoot); } } 将解析为您的工作目录。因此,为了更好地确定在何处编写文件,它会考虑采用以下方法。

isatty(STDIN_FILENO)

希望这有帮助。

答案 4 :(得分:1)

我摆脱了peter.petrov的回答,但让我解释一下在何处进行文件编辑以将其更改为相对路径。

只需编辑“ AXLAPIService.java”并更改

url = new URL("file:C:users..../schema/current/AXLAPI.wsdl");

url = new URL("file:./schema/current/AXLAPI.wsdl");

或您想存储它的任何地方。

您仍然可以将wsdl文件打包到jar中的meta-inf文件夹中,但这是使它对我有用的最简单方法。

答案 5 :(得分:0)

只是与问题略有关系,但试着围绕这个问题。如此不直观:

import java.nio.file.*;
class Main {
  public static void main(String[] args) {
    Path p1 = Paths.get("/personal/./photos/./readme.txt");
    Path p2 = Paths.get("/personal/index.html");
    Path p3 = p1.relativize(p2);
    System.out.println(p3); //prints  ../../../../index.html  !!
  }
}