Java : File.toURI().toURL() on Windows file

2022-09-03 07:12:22

我运行的系统是Windows XP,带有JRE 1.6。

我这样做:

public static void main(String[] args) {
    try {
        System.out.println(new File("C:\\test a.xml").toURI().toURL());
    } catch (Exception e) {
        e.printStackTrace();
    }       
}

我得到这个:file:/C:/test%20a.xml

为什么给定的URL在前面没有两个斜杠?我期待.这是正常行为吗?C:file://C:...


编辑:

来自 Java 源代码 : java.net.URLStreamHandler.toExternalForm(URL)

    result.append(":");
    if (u.getAuthority() != null && u.getAuthority().length() > 0) {
        result.append("//");
        result.append(u.getAuthority());
    }

文件 URL 的颁发机构部分似乎为空或空,因此跳过了双斜杠。那么URL的权威部分是什么,它真的没有在文件协议中吗?


答案 1

这是一个有趣的问题。

首先:我在JRE6上得到了相同的结果。当我删除toURL()部分时,我甚至会得到它。

RFC2396 实际上不需要两个斜杠。根据第3节:

URI 语法依赖于该方案。通常,绝对 URI 编写如下:

<scheme>:<scheme-specific-part>

话虽如此,RFC2396已被RFC3986取代,RFC3986指出

通用 URI 语法由称为方案、颁发机构、路径、查询和片段的 omponent 的分层序列组成。

  URI         = scheme ":" hier-part [ "?" query ] [ "#" fragment ]

  hier-part   = "//" authority path-abempty
              / path-absolute
              / path-rootless
              / path-empty

方案和路径组件是必需的,尽管路径可能为空(无字符)。当权威存在时,路径必须为空或以斜杠 (“/”) 字符开头。当权限不存在时,路径不能以两个斜杠字符 (“//”) 开头。这些限制导致路径有五个不同的 ABNF 规则(第 3.3 节),其中只有一个规则与任何给定的 URI 引用匹配。

所以,你去吧。由于文件 URI 没有权限段,因此禁止它们以 // 开头。

但是,该RFC直到2005年才出现,Java引用了RFC2396,所以我不知道为什么它遵循此约定,因为新RFC之前的文件URL总是有两个斜杠。


答案 2

要回答为什么您可以同时拥有两者:

file:/path/file
file:///path/file
file://localhost/path/file

RFC3986 (3.2.2.主机)状态:

“如果 URI 方案定义了主机的默认值,则当主机子组件未定义或注册名称为空(长度为零)时,将应用该默认值。例如,定义了“文件”URI 方案,以便没有权限、空主机和“localhost”都表示最终用户的计算机,而“http”方案则认为缺少颁发机构或空主机无效。

因此,“file”方案转换为具有最终用户计算机的上下文,即使权限是空主机。file:///path/file