Конвертировать URL в обычное имя файла Windows Java - PullRequest
52 голосов
/ 29 мая 2011

Есть ли способ преобразовать это:

/C:/Users/David/Dropbox/My%20Programs/Java/Test/bin/myJar.jar

в это?:

C:\Users\David\Dropbox\My Programs\Java\Test\bin\myJar.jar

Я использую следующий код, который возвращает полный путь к архиву .JAR или каталогу / bin.

fullPath = new String(MainInterface.class.getProtectionDomain()
            .getCodeSource().getLocation().getPath());

Проблема в том, что getLocation() возвращает URL, и мне нужно нормальное имя файла Windows. Я попытался добавить следующее после getLocation():

toString() и toExternalForm() оба возвращают:

file:/C:/Users/David/Dropbox/My%20Programs/Java/Test/bin/

getPath() возвращает:

/C:/Users/David/Dropbox/My%20Programs/Java/Test/bin/

Обратите внимание на %20, которое следует преобразовать в пробел.

Есть ли быстрый и простой способ сделать это?

Ответы [ 6 ]

72 голосов
/ 26 июля 2013

Текущая рекомендация (с JDK 1.7+) - конвертировать URL → URI → путь. Таким образом, чтобы преобразовать URL-адрес в файл, вы должны сказать Paths.get(url.toURI()).toFile(). Если вы еще не можете использовать JDK 1.7, я бы порекомендовал new File(URI.getSchemeSpecificPart()).

Преобразование файла → URI. Сначала я покажу вам несколько примеров того, какие URI вы можете получить в Java.

                          -classpath URLClassLoader File.toURI()                Path.toUri()
C:\Program Files          file:/C:/Program%20Files/ file:/C:/Program%20Files/   file:///C:/Program%20Files/
C:\main.c++               file:/C:/main.c++         file:/C:/main.c++           file:///C:/main.c++
\\VBOXSVR\Downloads       file://VBOXSVR/Downloads/ file:////VBOXSVR/Downloads/ file://VBOXSVR/Downloads/
C:\Résume.txt             file:/C:/R%c3%a9sume.txt  file:/C:/Résume.txt         file:///C:/Résume.txt
\\?\C:\Windows (non-path) file://%3f/C:/Windows/    file:////%3F/C:/Windows/    InvalidPathException

Некоторые наблюдения об этих URI:

  • Спецификации URI: RFC 1738: URL , заменен RFC 2396: URI , заменен RFC 3986: URI . (WHATWG также имеет спецификацию URI , но она не определяет, как следует интерпретировать файловые URI.) Любые зарезервированные символы в пути указываются в процентах, а символы не ascii в URI - в процентах цитируется при вызове URI.toASCIIString ().
  • File.toURI () хуже, чем Path.toUri (), потому что File.toURI () возвращает необычный не RFC 1738 URI (дает файл: / вместо file: ///) и не форматирует URI для путей UNC в соответствии с предпочтительным форматом Microsoft . Однако ни один из этих URI UNC не работает в Firefox (для Firefox требуется файл: /////).
  • Путь более строг, чем Файл; вы не можете создать неверный путь из префикса «\. \» . «Эти префиксы не используются как часть самого пути», но они могут быть переданы в Win32 API.

Преобразование URI → файл: попробуем преобразовать предыдущие примеры в файлы:

                            new File(URI)            Paths.get(URI)           new File(URI.getSchemeSpecificPart())
file:///C:/Program%20Files  C:\Program Files         C:\Program Files         C:\Program Files
file:/C:/Program%20Files    C:\Program Files         C:\Program Files         C:\Program Files
file:///C:/main.c++         C:\main.c++              C:\main.c++              C:\main.c++
file://VBOXSVR/Downloads/   IllegalArgumentException \\VBOXSVR\Downloads\     \\VBOXSVR\Downloads
file:////VBOXSVR/Downloads/ \\VBOXSVR\Downloads      \\VBOXSVR\Downloads\     \\VBOXSVR\Downloads
file://///VBOXSVR/Downloads \\VBOXSVR\Downloads      \\VBOXSVR\Downloads\     \\VBOXSVR\Downloads
file://%3f/C:/Windows/      IllegalArgumentException IllegalArgumentException \\?\C:\Windows
file:////%3F/C:/Windows/    \\?\C:\Windows           InvalidPathException     \\?\C:\Windows

Опять же, использование Paths.get(URI) предпочтительнее, чем new File(URI), поскольку Path может обрабатывать UNC URI и отклонять неверные пути с префиксом \? \. Но если вы не можете использовать Java 1.7, скажите new File(URI.getSchemeSpecificPart()).

Кстати, не используйте URLDecoder для декодирования URL файла. Для файлов, содержащих «+», таких как «file: /// C: /main.c++», URLDecoder превратит его в «C: \ main.c»! URLDecoder предназначен только для синтаксического анализа представлений HTML-форм application / x-www-form-urlencoded в запросе URI (param=value&param=value), но не для удаления пути из URI без кавычек.

2014-09: отредактировано для добавления примеров.

17 голосов
/ 29 мая 2011
String path = "/c:/foo%20bar/baz.jpg";
path = URLDecoder.decode(path, "utf-8");
path = new File(path).getPath();
System.out.println(path); // prints: c:\foo bar\baz.jpg
3 голосов
/ 17 апреля 2014

Как уже упоминалось - getLocation () возвращает URL. Файл может легко преобразовать URI в путь, поэтому для меня самый простой способ - просто использовать:

File fullPath = new File(MainInterface.class.getProtectionDomain().
    getCodeSource().getLocation().toURI());

Конечно, если вам действительно нужна строка, просто измените на:

String fullPath = new File(MainInterface.class.getProtectionDomain().
    getCodeSource().getLocation().toURI()).toString();

Вам вообще не нужен URLDecoder.

2 голосов
/ 19 декабря 2015

Здравствуйте, смущенные люди из будущего. Здесь есть нюанс в конфигурации пути к файлу. Путь, который вы задаете для TESSDATA_PREFIX, используется внутри программы C ++ tesseract, не оболочкой Java. Это означает, что если вы используете окна, вам нужно заменить начальную косую черту и заменить все другие прямые косые черты. Очень хакерский обходной путь выглядит так:

URL pathUrl = this.getClass().getResource(TESS_DATA_PATH);
String pathStr = pathUrl.getPath();

// hack to get around windows using \ instead of /
if (SystemUtils.IS_OS_WINDOWS) {
  pathStr = pathStr.substring(1);
  pathStr = pathStr.replaceAll("/", "\\\\");
}
2 голосов
/ 03 августа 2012

Текущие ответы кажутся мне подозрительными.

java.net.URL.getFile

превращает URL файла, такой как этот

java.net.URL = file:/C:/some/resource.txt

в это

java.lang.String = /C:/some/resource.txt

так что вы можете использовать этот конструктор

new File(url.getFile)

чтобы указать путь к Windows

java.io.File = C:\some\resource.txt
2 голосов
/ 29 мая 2011

Вам нужен следующий код:

String path = URLDecoder.decode("/C:/Users/David/Dropbox/My%20Programs/Java/Test/bin/", "UTF-8");
System.out.println(new File(path).getPath());
...