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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21060992/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 06:17:42  来源:igfitidea点击:

How does Java resolve a relative path in new File()?

javafilerelative-path

提问by Eswar

I am trying to understand the way Java resolves relative path in while creating a Fileobject.

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

OS used: Windows

使用的操作系统:Windows

For the below snippet, I am getting an IOExceptionas it cannot find the path:

对于下面的代码片段,我得到了一个,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();
        }
}

My understanding here is, Java treats the path provided as absolute and returns an error when the path does not exist. So it makes sense.

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

When I update the above code to use relative path:

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

@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();
        }    
    }

It creates a new file and provides the below output:

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

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

In this case, my assumption is, even though the path provided doesn't exist, because the path contains "/../", java treats this as a relative path and creates the file in the user.dir. So this also makes sense.

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

But if I update the relative path as below:

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

   @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();
        }
    }

Then I get IOException: Access is denied.

然后我得到 IOException: Access is denied。

My questions are:

我的问题是:

  1. why "test/../test.txt"is treated as a relative path and creates the file in "user.dir"but"test/../../test.txt"returns an error? Where does it attempt to create the file for the path "test/../../test.txt"?
  2. When the specified relative path is not found, the file seems to be created in the user.dir. So, it appears to me that the below two scenarios does the same thing:

    //scenario 1
    File f = new File("test/../test.txt");
    f.createNewFile();
    
    //scenario 2
    File f = new File("test.txt");
    f.createNewFile();
    
  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();
    

So is there a real world case where one would use scenario 1 instead of scenario 2?

那么是否存在真实世界的案例,人们会使用场景 1 而不是场景 2?

I suppose I am missing something obvious here or have fundamentally misunderstood relative paths. I went through the Java docs for File and I am not able to find an explanation for this. There are quite a few questions posted in Stack Overflow regarding relative paths, but the ones I looked up were for specific scenarios and not exactly about how relative paths are resolved.

我想我在这里遗漏了一些明显的东西,或者从根本上误解了相对路径。我浏览了 File 的 Java 文档,但找不到对此的解释。Stack Overflow 上发布了很多关于相对路径的问题,但我查找的问题是针对特定场景的,并不完全是关于如何解决相对路径的。

It will be great if someone could please explain me how this works or point to some related links?

如果有人可以向我解释这是如何工作的或指向一些相关链接,那就太好了?

采纳答案by peter.petrov

There is a concept of a working directory.
This directory is represented by a .(dot).
In relative paths, everything else is relative to it.

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

Simply put the .(the working directory) is where you run your program.
In some cases the working directory can be changed but in general this is
what the dot represents. I think this is C:\JavaForTesters\in your case.

简单地说.(工作目录)就是你运行程序的地方。
在某些情况下,工作目录可以更改,但通常这就是
点所代表的内容。我认为这就是C:\JavaForTesters\你的情况。

So test\..\test.txtmeans: the sub-directory test
in my working directory, then one level up, then the
file test.txt. This is basically the same as just test.txt.

所以test\..\test.txt意味着:test
我的工作目录中的子目录,然后上一级,然后是
文件test.txt. 这与 just 基本相同test.txt

For more details check here.

有关更多详细信息,请查看此处。

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

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

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

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

回答by Tim B

The working directory is a common concept across virtually all operating systems and program languages etc. It's the directory in which your program is running. This is usually (but not always, there are ways to change it) the directory the application is in.

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

Relative paths are ones that start without a drive specifier. So in linux they don't start with a /, in windows they don't start with a C:\, etc. These always start from your working directory.

相对路径是没有驱动器说明符的路径。所以在 linux 中它们不以 a 开头/,在 windows 中它们不以 a 开头C:\,等等。这些总是从你的工作目录开始。

Absolute paths are the ones that start with a drive (or machine for network paths) specifier. They always go from the start of that drive.

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

回答by Andrey Chaschev

When your path starts with a root dir i.e. C:\in windows or /in Unix or in java resources path, it is considered to be an absolute path. Everything else is relative, so

当您的路径以根目录开头时,即C:\在 windows 或/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")

The major difference between getAbsolutePathand getCanonicalPathis that the first one concatenates a parent and a child path, so it may contain dots: ..or .. getCanonicalPathwill always return the same path for a particular file.

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

Note: File.equalsuses an abstract form of a path (getAbsolutePath) to compare files, so this means that two Fileobjects for the same might not be equal and Files are unsafe to use in collections like Mapor Set.

注意:File.equals使用抽象形式的路径 ( getAbsolutePath) 来比较文件,因此这意味着File相同的两个对象可能不相等,并且Files 在像Mapor 之类的集合中使用是不安全的Set

回答by Ricard Molins

On windows and Netbeans you can set the relative path as:

在 Windows 和 Netbeans 上,您可以将相对路径设置为:

    new FileReader("src\PACKAGE_NAME\FILENAME");

On Linux and Netbeans you can set the relative path as:

在 Linux 和 Netbeans 上,您可以将相对路径设置为:

    new FileReader("src/PACKAGE_NAME/FILENAME");

If you have your code inside Source PackagesI do not know if it is the same for eclipse or other IDE

如果你有你的代码,Source Packages我不知道它是否与 eclipse 或其他 IDE 相同

回答by djangofan

Only slightly related to the question, but try to wrap your head around this one. So un-intuitive:

仅与问题略有相关,但请尝试围绕这个问题。太不直观了:

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  !!
  }
}

回答by Ravi Tiwari

Relative paths can be best understood if you know how Java runs the program.

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

There is a concept of working directory when running programs in Java. Assuming you have a class, say, FileHelperthat does the IO under /User/home/Desktop/projectRoot/src/topLevelPackage/.

在 Java 中运行程序时有一个工作目录的概念。假设你有一个类,FileHelper它在 /User/home/Desktop/projectRoot/src/topLevelPackage/.

Depending on the case where you invoke javato run the program, you will have different working directory. If you run your program from within and IDE, it will most probably be projectRoot.

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

  • In this case $ projectRoot/src : java topLevelPackage.FileHelperit will be src.

  • In this case $ projectRoot : java -cp src topLevelPackage.FileHelperit will be projectRoot.

  • In this case $ /User/home/Desktop : java -cp ./projectRoot/src topLevelPackage.FileHelperit will be Desktop.

  • 在这种情况下$ 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)

(Assuming $ is your command prompt with standard Unix-like FileSystem. Similar correspondence/parallels with Windows system)

So, your relative path root (.)resolves to your working directory. Thus to be better sure of where to write files, it's said to consider below approach.

因此,您的相对路径 root(.)解析为您的工作目录。因此,为了更好地确定写入文件的位置,据说可以考虑以下方法。

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);

    }
}

Hope this helps.

希望这可以帮助。

回答by Christopher

I went off of peter.petrov's answer but let me explain where you make the file edits to change it to a relative path.

我离开了 peter.petrov 的回答,但让我解释一下您在哪里进行文件编辑以将其更改为相对路径。

Simply edit "AXLAPIService.java" and change

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

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

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

to

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

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

or where ever you want to store it.

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

You can still work on packaging the wsdl file into the meta-inf folder in the jar but this was the simplest way to get it working for me.

您仍然可以将 wsdl 文件打包到 jar 中的 meta-inf 文件夹中,但这是让它为我工作的最简单方法。