Генерация канонического пути

Делает любой знает о любых библиотеках Java, которыми я мог пользоваться для генерации канонических путей (в основном удаляют обратные ссылки).

Мне нужно что-то, что сделает следующее:

Необработанный Путь-> Канонический Путь

/../foo/       -> /foo
/foo/          -> /foo
/../../../     -> /
/./foo/./      -> /foo
//foo//bar     -> /foo/bar
//foo/../bar   -> /bar

и т.д...

В данный момент я лениво полагаюсь на использование:

 new File("/", path).getCanonicalPath();

Но это разрешает путь против фактической файловой системы и синхронизируется.

   java.lang.Thread.State: BLOCKED (on object monitor)
        at java.io.ExpiringCache.get(ExpiringCache.java:55)
        - waiting to lock <0x93a0d180> (a java.io.ExpiringCache)
        at java.io.UnixFileSystem.canonicalize(UnixFileSystem.java:137)
        at java.io.File.getCanonicalPath(File.java:559)

Пути, которые я канонизирую, не существуют в моей файловой системе, поэтому просто логика метода сделает меня прекрасный, таким образом не требуя никакой синхронизации. Я надеюсь на хорошо протестированную библиотеку вместо того, чтобы иметь необходимость записать мое собственное.

22
задан Lance Roberts 18 February 2013 в 23:44
поделиться

2 ответа

Я думаю, вы можете использовать класс URI для этого; например если путь не содержит символов, которые нужно экранировать в компоненте пути URI, вы можете это сделать.

String normalized = new URI(path).normalize().getPath();

Если путь содержит (или может содержать) символы, которые необходимо экранировать, конструкторы с несколькими аргументами будут экранировать аргумент path , и вы можете предоставить null для других аргументов.

Примечания:

  1. Вышеупомянутое нормализует путь к файлу, рассматривая его как относительный URI. Если вы хотите нормализовать весь URI ... включая (необязательную) схему, полномочия и другие компоненты, не вызывайте getPath () !

  2. Нормализация URI не требует просмотра файловой системы, как это делает канонизация файлов. Но обратная сторона - то, что нормализация ведет себя иначе, чем каноникализация, когда в пути есть символические ссылки.

21
ответ дан 29 November 2019 в 04:08
поделиться

Вы можете попробовать такой алгоритм:

String collapsePath(String path) {
    /* Split into directory parts */
    String[] directories = path.split("/");
    String[] newDirectories = new String[directories.length];
    int i, j = 0;

    for (i=0; i<directories.length; i++) {
        /* Ignore the previous directory if it is a double dot */
        if (directories[i].equals("..") && j > 0)
            newDirectories[j--] = "";
        /* Completely ignore single dots */
        else if (! directories[i].equals("."))
            newDirectories[j++] = directories[i];
    }

    /* Ah, what I would give for String.join() */
    String newPath = new String();
    for (i=0; i < j; i++)
        newPath = newPath + "/" + newDirectories[i];
    return newPath;
}

Он не идеален; он линейен по количеству каталогов, но делает копию в памяти.

4
ответ дан 29 November 2019 в 04:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: