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

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

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

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

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.

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

......

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

This question is related to java windows url

The answer is


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


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:

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

For Java 8 the following method works:

  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)

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

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

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

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.

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


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

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

Note: In my context I will receive absolute paths. I have tested this on Windows and 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("____________________________________________________________");
    }

}

Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to windows

"Permission Denied" trying to run Python on Windows 10 A fatal error occurred while creating a TLS client credential. The internal error state is 10013 How to install OpenJDK 11 on Windows? I can't install pyaudio on Windows? How to solve "error: Microsoft Visual C++ 14.0 is required."? git clone: Authentication failed for <URL> How to avoid the "Windows Defender SmartScreen prevented an unrecognized app from starting warning" XCOPY: Overwrite all without prompt in BATCH Laravel 5 show ErrorException file_put_contents failed to open stream: No such file or directory how to open Jupyter notebook in chrome on windows Tensorflow import error: No module named 'tensorflow'

Examples related to url

What is the difference between URL parameters and query strings? Allow Access-Control-Allow-Origin header using HTML5 fetch API File URL "Not allowed to load local resource" in the Internet Browser Slack URL to open a channel from browser Getting absolute URLs using ASP.NET Core How do I load an HTTP URL with App Transport Security enabled in iOS 9? Adding form action in html in laravel React-router urls don't work when refreshing or writing manually URL for public Amazon S3 bucket How can I append a query parameter to an existing URL?