Відповіді:
Розглянемо ці імена файлів:
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клас намагається представити уявлення про те, що НД любить називати "ієрархічними іменами шляху" (в основному це шлях, як 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властивість системи повертається, то цей метод поверне "повне" ім'я файлу.
Path.toAbsolutePath().normalize()що є хорошим середнім середовищем між канонічним (реальним) шляхом та абсолютним шляхом.