Подтвердить что ты не робот

Преобразование URL в обычное имя файла Windows

Есть ли способ сделать это:

/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, который должен быть преобразован в пробел.

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

4b9b3361

Ответ 1

Текущая рекомендация (с 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 (дает файл:/вместо файла:///) и не форматирует URI для UNC-путей в соответствии с предпочтительным форматом Microsoft. Ни один из этих URI UNC не работает в Firefox, хотя (для Firefox требуется файл://///).
  • Путь более строгий, чем файл; вы не можете создать недопустимый путь из "\.\" префикса. "Эти префиксы не используются как часть самого пути", но они могут быть переданы в API Win32.

Преобразование 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 может обрабатывать URI UNC и отклонять недопустимые пути с префиксом \? \. Но если вы не используете Java 1.7, скажите new File(URI.getSchemeSpecificPart()).

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

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

Ответ 2

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

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

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

Ответ 4

Ниже приведен код:

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

Ответ 5

Как уже упоминалось - 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.

Ответ 6

Привет, смущенные люди из будущего. Здесь есть нюанс конфигурации пути к файлу. Путь, который вы устанавливаете для TESSDATA_PREFIX, используется внутри программы 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("/", "\\\\");
}