将 Java file:// URL 转换为 File(...) 路径,平台无关,包括 UNC 路径

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18520972/
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-12 08:44:00  来源:igfitidea点击:

Converting Java file:// URL to File(...) path, platform independent, including UNC paths

javawindowsurl

提问by Christian Fries

I am developing a platform independent application. I am receiving a file URL*. On windows these are:

我正在开发一个独立于平台的应用程序。我收到一个文件 URL*。在 Windows 上,这些是:

  • file:///Z:/folder%20to%20file/file.txt

  • file://host/folder%20to%20file/file.txt(an UNC path)

  • file:///Z:/folder%20to%20file/file.txt

  • file://host/folder%20to%20file/file.txt(UNC 路径)

I am using new File(URI(urlOfDocument).getPath())which works fine with the first one and also on Unix, Linux, OS X, but does not work with UNC paths.

我正在使用new File(URI(urlOfDocument).getPath())它在第一个和 Unix、Linux、OS X 上工作正常,但不适用于 UNC 路径。

What is the standard way to convert file: URLs to File(..) paths, being compatible with Java 6?

转换文件的标准方法是什么:URL 到 File(..) 路径,与 Java 6 兼容?

......

......

* Note: I am receiving theses URLs from OpenOffice / LibreOffice (XModel.getURL()).

* 注意:我从 OpenOffice / LibreOffice (XModel.getURL()) 收到这些 URL。

回答by Simone Gianni

Java (at least 5 and 6, java 7 Paths solved most) has a problem with UNC and URI. Eclipse team wrapped it up here : http://wiki.eclipse.org/Eclipse/UNC_Paths

Java(至少5和6,java 7 Paths解决最多)UNC和URI有问题。Eclipse 团队将其打包在这里:http: //wiki.eclipse.org/Eclipse/UNC_Paths

From java.io.File javadocs, the UNC prefix is "////", and java.net.URI handles file:////host/path (four slashes).

在 java.io.File javadocs 中,UNC 前缀是“////”,java.net.URI 处理 file:////host/path(四个斜线)。

More details on why this happens and possible problems it causes in other URI and URL methods can be found in the list of bugs at the end of the link given above.

关于为什么会发生这种情况以及它在其他 URI 和 URL 方法中可能导致的问题的更多详细信息,可以在上面给出的链接末尾的错误列表中找到。

Using these informations, Eclipse team developed org.eclipse.core.runtime.URIUtil class, which source code can probably help out when dealing with UNC paths.

使用这些信息,Eclipse 团队开发了 org.eclipse.core.runtime.URIUtil 类,该类源代码在处理 UNC 路径时可能会有所帮助。

回答by Christian Fries

Based on the hint and link provided in Simone Giannis answer, this is my hackto fix this.

根据 Simone Giannis 回答中提供的提示和链接,这是我解决此问题的技巧

I am testing on uri.getAuthority(), because UNC path will report an Authority. This is a bug - so I rely on the existence of a bug, which is evil, but it apears as if this will stay forever (since Java 7 solves the problem in java.nio.Paths).

我正在 uri.getAuthority() 上进行测试,因为 UNC 路径将报告一个权限。这是一个错误 - 所以我依赖一个错误的存在,这是邪恶的,但它似乎会永远存在(因为 Java 7 解决了 java.nio.Paths 中的问题)。

Note: In my context I will receive absolute paths. I have tested this on Windows and OS X.

注意:在我的上下文中,我将收到绝对路径。我已经在 Windows 和 OS X 上测试过了。

(Still looking for a better way to do it)

(仍在寻找更好的方法来做到这一点)

package com.christianfries.test;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;

public class UNCPathTest {

    public static void main(String[] args) throws MalformedURLException, URISyntaxException {
        UNCPathTest upt = new UNCPathTest();

        upt.testURL("file://server/dir/file.txt");  // Windows UNC Path

        upt.testURL("file:///Z:/dir/file.txt");     // Windows drive letter path

        upt.testURL("file:///dir/file.txt");        // Unix (absolute) path
    }

    private void testURL(String urlString) throws MalformedURLException, URISyntaxException {
        URL url = new URL(urlString);
        System.out.println("URL is: " + url.toString());

        URI uri = url.toURI();
        System.out.println("URI is: " + uri.toString());

        if(uri.getAuthority() != null && uri.getAuthority().length() > 0) {
            // Hack for UNC Path
            uri = (new URL("file://" + urlString.substring("file:".length()))).toURI();
        }

        File file = new File(uri);
        System.out.println("File is: " + file.toString());

        String parent = file.getParent();
        System.out.println("Parent is: " + parent);

        System.out.println("____________________________________________________________");
    }

}

回答by judovana

I hope (not exactly verified) that newer java brought nio package and Path. Hopefully it have it fixed:String s="C:\\some\\ile.txt"; System.out.println(new File(s).toPath().toUri());

我希望(未完全验证)较新的 java 带来了 nio 包和路径。希望它已修复:String s="C:\\some\\ile.txt"; System.out.println(new File(s).toPath().toUri());

回答by Markus Pscheidt

Building on @SotiriosDelimanolis's comment, here is a method to deal with URLs (such as file:...) and non-URLs (such as C:...), using Spring's FileSystemResource:

基于@SotiriosDelimanolis 的评论,这里有一种方法来处理 URL(例如 file:...)和非 URL(例如 C:...),使用 Spring 的 FileSystemResource:

public FileSystemResource get(String file) {
    try {
        // First try to resolve as URL (file:...)
        Path path = Paths.get(new URL(file).toURI());
        FileSystemResource resource = new FileSystemResource(path.toFile());
        return resource;
    } catch (URISyntaxException | MalformedURLException e) {
        // If given file string isn't an URL, fall back to using a normal file 
        return new FileSystemResource(file);
    }
}

回答by Ironluca

For Java 8 the following method works:

对于 Java 8,以下方法有效:

  1. Form an URI from file URI string
  2. Create a file from the URI (not directly from URI string, absolute URI string are not paths)
  1. 从文件 URI 字符串形成 URI
  2. 从 URI 创建文件(不是直接从 URI 字符串,绝对 URI 字符串不是路径)

Refer, below code snippet

参考,下面的代码片段

    String fileURiString="file:///D:/etc/MySQL.txt";
    URI fileURI=new URI(fileURiString);
    File file=new File(fileURI);//File file=new File(fileURiString) - will generate exception

    FileInputStream fis=new FileInputStream(file);
    fis.close();