Ответы:
Рассмотрим эти имена файлов:
C:\temp\file.txt
- Это путь, абсолютный путь и канонический путь.
.\file.txt
- Это путь. Это не абсолютный и не канонический путь.
C:\temp\myapp\bin\..\\..\file.txt
- Это путь и абсолютный путь. Это не канонический путь.
Канонический путь - это всегда абсолютный путь.
Преобразование из пути в канонический путь делает его абсолютным (обычно это привязка к текущему рабочему каталогу, например, ./file.txt
становится c:/temp/file.txt
). Канонический путь к файлу просто «очищает» путь, удаляя и разрешая такие вещи, как ..\
и разрешая символические ссылки (в unixes).
Также обратите внимание на следующий пример с nio.Paths:
String canonical_path_string = "C:\\Windows\\System32\\";
String absolute_path_string = "C:\\Windows\\System32\\drivers\\..\\";
System.out.println(Paths.get(canonical_path_string).getParent());
System.out.println(Paths.get(absolute_path_string).getParent());
Хотя оба пути относятся к одному и тому же местоположению, выходные данные будут совершенно разными:
C:\Windows
C:\Windows\System32\drivers
C:\temp\file.txt
это канонический путь - временный каталог может быть мягкой ссылкой файловой системы или жесткой ссылкой (соединение в NTFS), а file.txt может быть мягкой ссылкой. Я не знаю, могут ли файловые системы различать жесткие ссылки на файлы.
getAbsolutePath()
вместо getCanonicalPath()
. Это даже выглядит лучше, потому что канонический автоматически разрешает эти ../
части.
getCanonicalPath
бросает какое- IOException
то время getAbsolutePath
нет, если это соображение.
Лучший способ почувствовать такие вещи - попробовать их:
import java.io.File;
public class PathTesting {
public static void main(String [] args) {
File f = new File("test/.././file.txt");
System.out.println(f.getPath());
System.out.println(f.getAbsolutePath());
try {
System.out.println(f.getCanonicalPath());
}
catch(Exception e) {}
}
}
Ваш вывод будет примерно таким:
test\..\.\file.txt
C:\projects\sandbox\trunk\test\..\.\file.txt
C:\projects\sandbox\trunk\file.txt
Итак, getPath()
дает вам путь, основанный на объекте File, который может быть или не быть относительным; getAbsolutePath()
дает вам абсолютный путь к файлу; и getCanonicalPath()
дает вам уникальный абсолютный путь к файлу. Обратите внимание, что существует огромное количество абсолютных путей, которые указывают на один и тот же файл, но только один канонический путь.
Когда использовать каждый? Зависит от того, что вы пытаетесь выполнить, но если вы пытаетесь увидеть Files
, указывают ли два файла на один и тот же файл на диске, вы можете сравнить их канонические пути. Всего один пример.
but if you were trying to see if two Files are pointing at the same file on disk
Как? пример пожалуйста?
Короче говоря:
getPath()
получает строку пути, с которой File
был построен объект, и это может быть относительный текущий каталог.getAbsolutePath()
получает строку пути после разрешения ее относительно текущего каталога, если он относительный, в результате чего получается полный путь.getCanonicalPath()
получает строку пути после разрешения любого относительного пути к текущему каталогу и удаляет все относительные пути ( .
и ..
) и любые ссылки файловой системы, чтобы вернуть путь, который файловая система считает каноническим средством для ссылки на объект файловой системы, на который она указывает.Кроме того, каждый из них имеет файловый эквивалент, который возвращает соответствующий File
объект.
getPath()
возвращает путь, использованный для создания File
объекта. Это возвращаемое значение не изменяется в зависимости от местоположения, в котором оно выполняется (результаты ниже для окон, разделители, очевидно, отличаются в других местах)
File f1 = new File("/some/path");
String path = f1.getPath(); // will return "\some\path"
File dir = new File("/basedir");
File f2 = new File(dir, "/some/path");
path = f2.getPath(); // will return "\basedir\some\path"
File f3 = new File("./some/path");
path = f3.getPath(); // will return ".\some\path"
getAbsolutePath()
разрешит путь в зависимости от места выполнения или диска. Так что если бежать из c:\test
:
path = f1.getAbsolutePath(); // will return "c:\some\path"
path = f2.getAbsolutePath(); // will return "c:\basedir\some\path"
path = f3.getAbsolutePath(); // will return "c:\test\.\basedir\some\path"
getCanonicalPath()
зависит от системы. Это разрешит уникальное местоположение, которое представляет путь. Так что если у вас есть какие-либо "." В пути, они обычно будут удалены.
Что касается того, когда их использовать. Это зависит от того, чего вы пытаетесь достичь. getPath()
полезно для мобильности. getAbsolutePath()
полезно, чтобы найти расположение файловой системы, и getCanonicalPath()
особенно полезно, чтобы проверить, совпадают ли два файла.
getCanonicalPath() is particularly useful to check if two files are the same.
Главное, чтобы вы могли поразмыслить над тем, что File
класс пытается представить представление о том, что Sun любит называть «иерархическими путями» (в основном это путь, похожий на c:/foo.txt
или /usr/muggins
). Вот почему вы создаете файлы с точки зрения путей. Все операции, которые вы описываете, являются операциями с этим «путем».
getPath()
извлекает путь, по которому был создан файл ( ../foo.txt
)getAbsolutePath()
извлекает путь, с помощью которого был создан файл, но включает информацию о текущем каталоге, если путь относительный ( /usr/bobstuff/../foo.txt
)getCanonicalPath()
пытается получить уникальное представление об абсолютном пути к файлу. Это устраняет косвенность от ".." и "." ссылки ( /usr/foo.txt
).Заметьте, я говорю попытки - при формировании канонического пути виртуальная машина может бросить IOException
. Обычно это происходит потому, что он выполняет некоторые операции с файловой системой, любая из которых может дать сбой.
Я нахожу, что мне редко приходится использовать, getCanonicalPath()
но, если в Windows указан файл с именем файла в формате DOS 8.3, например, java.io.tmpdir
возвращаемое свойство System, этот метод возвращает «полное» имя файла.
Path.toAbsolutePath().normalize()
что это хорошая середина между каноническим (реальным) путем и только абсолютным путем.