File.separator和路径中的斜杠之间的区别


200

在Java Path-String中使用File.separator和普通法/有什么区别?

与双反斜杠相反,\\平台独立性似乎不是原因,因为两个版本都可以在Windows和Unix下运行。

public class SlashTest {
    @Test
    public void slash() throws Exception {
        File file = new File("src/trials/SlashTest.java");
        assertThat(file.exists(), is(true));
    }

    @Test
    public void separator() throws Exception {
        File file = new File("src" + File.separator + "trials" + File.separator + "SlashTest.java");
        assertThat(file.exists(), is(true));
    }
}

换个问题,如果/可以在Unix和Windows上运行,为什么要使用File.separator


5
@Ring“历史原因”是什么?
洛恩侯爵,

Answers:


245

使用用于处理文件的Java库,您可以/在所有平台上安全地使用(斜杠,而不是反斜杠)。库代码负责在内部将事物转换为特定于平台的路径。

File.separator但是,您可能要在UI中使用,因为最好向人们展示在他们的OS中有意义的东西,而不是对Java有意义的东西。

更新:经过五分钟的搜索,我一直无法找到记录的“您可以始终使用斜线”行为。现在,我确定已经看到了它的文档,但是由于找不到正式的参考文献(因为我的记忆力不佳),我坚持使用,File.separator因为您知道这是可行的。


2
这也可能是性能问题,因为您希望分隔符在运行时转换为其他格式。另外,不要期望这种情况会在所有不受支持的JVM中发生。
jpabluz 2010年

7
@TJ Crowder:“经过五分钟的搜索,我一直无法找到记录在案的'你总是可以使用斜杠'的行为。” 它不是JVM的功能,而是Windows NT API的功能。
Powerlord 2010年

12
@Powerlord:如果Windows也能做到,那就太好了-但是库(而不是JVM)也能做到。具体来说,File使用FileSystem.normalize所有的地方通过公共API收到“正常化”的路径,几乎任何与文件路径字符串交易(例如FileWriter(String))使用File在幕后。
TJ Crowder 2010年

9
从Java7开始,不再需要使用File.separator。将java.nio.file.Paths(Paths.get(first,more ...))用于dir到dir以及dir到文件名的连接要简单得多,也更干净。
magiccrafter

6
@jpabluz“性能问题”!你是认真的吗?考虑到将文件名放入磁盘后,转换对运行时的影响是微不足道的。任何JVM都应支持它,因为它是规范的一部分File
罗恩侯爵

316

File.separator之所以使用它,是因为有一天您的程序可能会在遥远的土地,陌生的事物和陌生的人的土地上开发的平台上运行,马在这里哭泣,母牛在操纵所有电梯。在这片土地上,人们传统上使用“:”字符作为文件分隔符,因此JVM忠于他们的意愿。


4
是的,Pointy真的把我们带到了Elbonia(希望他没有尖的发型;
Geek Pun

4
“……牛在操纵所有的电梯。” 同样,当我阅读时,我没有喝一口咖啡。辉煌。
TJ Crowder 2010年

8
在这样的国家/地区,您可以使用新的org.apache.chicken.elevators.OperatorUtility类,该类将所有这些疯狂之处嵌入其中,以方便您使用。
Brain

27

尽管使用File.separator引用文件名是过分的(对于那些想像遥远的人,我想他们的JVM实现将用替换a /:就像Windows jvm用替换了它\)。

但是,有时您会得到文件引用,而不是创建文件引用,并且需要解析它,并且要做到这一点,您需要了解平台上的分隔符。File.separator可以帮助您做到这一点。


11

好,让我们检查一些代码。
File.java第428至435行File.<init>

String p = uri.getPath();
if (p.equals(""))
    throw new IllegalArgumentException("URI path component is empty");

// Okay, now initialize
p = fs.fromURIPath(p);
if (File.separatorChar != '/')
p = p.replace('/', File.separatorChar);

让我们阅读fs/*(FileSystem)*/.fromURIPath()文档:

java.io.FileSystem
public abstract String fromURIPath(String path)
如有必要,对给定的URI路径字符串进行后处理。这在win32上使用,例如,将“ / c:/ foo”转换为“ c:/ foo”。路径字符串仍带有斜杠分隔符;此方法返回后,File类中的代码将转换它们。

这表示 FileSystem.fromURIPath()仅在Windows中才对URI路径进行后处理,因为在下一行中:

p = p.replace('/', File.separatorChar);

它用系统相关的替换每个“ /” seperatorChar,您可以始终确保“ /”在每个操作系统中都是安全的。


8

嗯,操作系统比Unix和Windows(便携式设备等)更多,而Java以其可移植性而闻名。最佳实践是使用它,因此JVM可以确定哪个操作系统最适合该操作系统。


这些操作系统大多数都运行UNIX的某种变体。旧的Mac样式:分隔符早已消失。似乎除了Windows之外的每个人都在使用该标准/。甚至Windows现在似乎都能很好地处理斜线。cd /windows/system从主系统驱动器上尝试Windows 10系统。虽然您仍然希望使用系统分隔符显示路径(以免混淆用户),但是您可以/在其他任何地方使用正斜杠,并确信代码可以在您可能会部署的任何地方使用。
Shadow Man

7

尽管在进入过程中并没有多大区别,但在返回过程中却有很大的不同。

当然,您可以在新的File(String path)中使用'/'或'\',但是File.getPath()只会给您其中之一。


轻微校正...在Windows中,您可以使用正斜杠/\\ 反斜杠。但是在其他任何地方,最好使用正斜杠,/否则会遇到问题。
Shadow Man

6

晚会。我在Windows 10上使用JDK 1.8和Eclipse MARS1。
我发现

getClass().getClassLoader().getResourceAsStream("path/to/resource");

工作和

getClass().getClassLoader().getResourceAsStream("path"+File.separator+"to"+File.separator+"resource");

不起作用,并且

getClass().getClassLoader().getResourceAsStream("path\to\resource");

不起作用。最后两个是等效的。所以...我有充分的理由不使用File.separator。


6
在此行中getClass().getClassLoader().getResourceAsStream("path\to\resource");,有一个制表\t符()和一个回车符(\r)。
Stephan

9
这与问题的情况不同。ClassLoader的getResourceAsStream方法不采用文件路径,而是采用文件系统上可能存在或可能不存在的资源名称,并记录为仅接受“ /”作为资源路径分隔符。
daiscog '16

@Stephan那里没有有趣的转义,因为File.separator是反斜杠。它仅在硬编码的字符串中被视为转义字符,您需要在其中转义反斜杠。如果您已将该字符存储在文本文件中,或者存储在或中charString则无需第二次对其进行转义,因为它已经被转换为预期的反斜杠字符。试试看这个自己看看:String backslash = "\\"; System.out.println("welcome" + backslash + "to" + backslash + "reality");
Shadow Man

2
@Stephan哦,我明白了…你在谈论第三行。你是对的。在该行(硬编码字符串)中,您需要转义转义字符。我的眼睛停在第二行,起初我什至没有注意到第三行。
暗影人

3

可移植性简单明了。


是的,对于便携性,就不能使用反斜杠。使用正斜杠/或系统分隔符File.separator。两者似乎无处不在。虽然File.separator可以保证在所有地方都可以使用,但简单的斜杠/似乎也可以在所有地方使用。如果它在某处不起作用,那么我很想听听它。我相信它将在所有系统上运行。至少,我还没有找到任何/行不通的地方(Mac OSX,Windows,* nix,Android,iOS-我尚未检查过使用“:”作为分隔符的OSX之前的Mac,OS / 2,NeXT或其他任何真正古老的OS)。
Shadow Man

1

“面向程序员的Java SE8”声称Java可以解决这两种情况。(第480页,最后一段)。该示例声称:

c:\Program Files\Java\jdk1.6.0_11\demo/jfc

将解析就好了。注意最后一个(Unix风格的)分隔符。

这是俗气的,并且可能容易出错,但这就是他们(Deitel和Deitel)所声称的。

我认为对人而不是Java的困惑是没有使用此功能的充分理由。



0

使用主机系统的命名约定指定文件或目录的路径名。但是,File类定义与平台有关的常量,这些常量可用于以与平台无关的方式处理文件和目录名称。

Files.seperator定义在路径名中分隔目录和文件组件的字符或字符串。对于Unix,Windows和Macintosh,此分隔符分别为'/','\'或':'。


对于Macintosh,“:”很古老。从OSX开始,由于Mac运行的是带有标准UNIX文件系统的UNIX形式,因此Mac也使用“ /”(正斜杠)。
Shadow Man


0

使用File.separator使Ubuntu生成的文件名上带有“ \”而不是目录。也许我对创建文件(和目录)的方式很懒,并且本可以避免这种情况,无论如何,每次都使用“ /”来避免名称上带有“ \”的文件


0

如果您尝试使用Linux分隔符从某个就绪路径(例如,保存在数据库中)从某个就绪路径创建文件,该怎么办?

也许只是使用路径来创建文件:

new File("/shared/folder/file.jpg");

但是Windows使用其他分隔符(\)。那么,将斜线分隔符转换为平台无关的替代方法吗?喜欢:

new File(convertPathToPlatformIndependent("/shared/folder"));

这个方法 convertPathToPlatformIndependent可能会有某种“ /”分割,并与File.separator联接。

好吧,对我来说,这对于平台无关的语言(对吗?)和Java已经支持在Windows或Linux上使用这不是很好/。但是,如果您正在使用路径,并且每次都必须记住进行此转换,这将是一场噩梦,并且您将来在应用程序上可能没有任何实际收获(也许在@Pointy描述的世界中)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.