Câu trả lời:
Hãy xem xét các tên tệp này:
C:\temp\file.txt
- Đây là một con đường, một con đường tuyệt đối và một con đường kinh điển.
.\file.txt
- Đây là một con đường. Đó không phải là một con đường tuyệt đối hay một con đường kinh điển.
C:\temp\myapp\bin\..\\..\file.txt
- Đây là một con đường và một con đường tuyệt đối. Đó không phải là một con đường kinh điển.
Một con đường kinh điển luôn luôn là một con đường tuyệt đối.
Chuyển đổi từ một đường dẫn đến một con đường kinh điển làm cho nó tuyệt đối (thường tack vào thư mục làm việc hiện tại nên ví dụ như ./file.txt
trở thành c:/temp/file.txt
). Đường dẫn chính tắc của một tệp chỉ "làm sạch" đường dẫn, loại bỏ và giải quyết các công cụ như ..\
và giải quyết các liên kết tượng trưng (trên unixes).
Cũng lưu ý ví dụ sau với 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());
Mặc dù cả hai đường dẫn đều chỉ đến cùng một vị trí, nhưng đầu ra sẽ khá khác nhau:
C:\Windows
C:\Windows\System32\drivers
C:\temp\file.txt
là một đường dẫn chính tắc - thư mục tạm thời có thể là liên kết mềm hệ thống tệp hoặc liên kết cứng (đường nối trong NTFS) và tệp file.txt có thể là liên kết mềm. Tôi không biết hệ thống tập tin có thể phân biệt các liên kết cứng đến tập tin.
getAbsolutePath()
thay vì getCanonicalPath()
. Nó thậm chí trông tốt hơn bởi vì một trong những kinh điển tự động giải quyết những ../
phần đó.
getCanonicalPath
ném một IOException
lúc getAbsolutePath
thì không, nếu đây là một sự cân nhắc.
Cách tốt nhất mà tôi đã tìm thấy để cảm nhận những thứ như thế này là thử chúng:
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) {}
}
}
Đầu ra của bạn sẽ giống như:
test\..\.\file.txt
C:\projects\sandbox\trunk\test\..\.\file.txt
C:\projects\sandbox\trunk\file.txt
Vì vậy, getPath()
cung cấp cho bạn đường dẫn dựa trên đối tượng Tệp, có thể có hoặc không tương đối; getAbsolutePath()
cung cấp cho bạn một đường dẫn tuyệt đối đến tập tin; và getCanonicalPath()
cung cấp cho bạn đường dẫn tuyệt đối duy nhất đến tệp. Lưu ý rằng có một số lượng lớn các đường dẫn tuyệt đối trỏ đến cùng một tệp, nhưng chỉ có một đường dẫn chính tắc.
Khi nào nên sử dụng mỗi? Phụ thuộc vào những gì bạn đang cố gắng thực hiện, nhưng nếu bạn đang cố gắng xem liệu hai người Files
có đang chỉ vào cùng một tệp trên đĩa hay không, bạn có thể so sánh các đường dẫn chính tắc của họ. Chỉ là một ví dụ.
but if you were trying to see if two Files are pointing at the same file on disk
Làm sao? làm ơn ví dụ?
Nói ngắn gọn:
getPath()
nhận được chuỗi đường dẫn mà File
đối tượng được xây dựng và nó có thể là thư mục hiện tại tương đối.getAbsolutePath()
nhận được chuỗi đường dẫn sau khi giải quyết nó theo thư mục hiện tại nếu nó tương đối, dẫn đến một đường dẫn đủ điều kiện.getCanonicalPath()
nhận được chuỗi đường dẫn sau khi giải quyết bất kỳ đường dẫn tương đối nào đối với thư mục hiện tại và xóa mọi đường dẫn tương đối ( .
và ..
) và bất kỳ hệ thống tệp nào liên kết để trả về một đường dẫn mà hệ thống tệp xem là phương tiện chính quy để tham chiếu đối tượng hệ thống tệp mà nó trỏ tới.Ngoài ra, mỗi trong số này có một tệp tương đương trả về File
đối tượng tương ứng .
getPath()
trả về đường dẫn được sử dụng để tạo File
đối tượng Giá trị trả về này không thay đổi dựa trên vị trí nó được chạy (kết quả bên dưới là cho các cửa sổ, dấu phân cách rõ ràng là khác ở nơi khác)
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()
sẽ giải quyết đường dẫn dựa trên vị trí thực hiện hoặc ổ đĩa. Vì vậy, nếu chạy từ 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()
là phụ thuộc hệ thống. Nó sẽ giải quyết vị trí duy nhất mà đường dẫn đại diện. Vì vậy, nếu bạn có bất kỳ "." Trong đường dẫn, chúng thường sẽ bị xóa.
Khi nào nên sử dụng chúng. Nó phụ thuộc vào những gì bạn đang cố gắng để đạt được. getPath()
là hữu ích cho tính di động.getAbsolutePath()
rất hữu ích để tìm vị trí hệ thống tệp và getCanonicalPath()
đặc biệt hữu ích để kiểm tra xem hai tệp có giống nhau không.
getCanonicalPath() is particularly useful to check if two files are the same.
Điều quan trọng khiến bạn phải suy nghĩ là File
lớp học cố gắng thể hiện một quan điểm về cái mà Sun muốn gọi là "tên đường dẫn phân cấp" (về cơ bản là một đường dẫn như c:/foo.txt
hoặc /usr/muggins
). Đây là lý do tại sao bạn tạo các tệp theo đường dẫn. Các hoạt động bạn đang mô tả là tất cả các hoạt động dựa trên "tên đường dẫn" này.
getPath()
tìm nạp đường dẫn mà Tệp được tạo bằng ( ../foo.txt
)getAbsolutePath()
tìm nạp đường dẫn mà Tệp đã được tạo, nhưng bao gồm thông tin về thư mục hiện tại nếu đường dẫn là tương đối ( /usr/bobstuff/../foo.txt
)getCanonicalPath()
cố gắng tìm nạp một đại diện duy nhất của đường dẫn tuyệt đối đến tệp. Điều này giúp loại bỏ sự gián tiếp từ ".." và "." tài liệu tham khảo ( /usr/foo.txt
).Lưu ý tôi nói các nỗ lực - khi hình thành Đường dẫn Canonical, VM có thể ném IOException
. Điều này thường xảy ra bởi vì nó đang thực hiện một số hoạt động của hệ thống tập tin, bất kỳ một trong số đó có thể thất bại.
Tôi thấy tôi hiếm khi có nhu cầu sử dụng getCanonicalPath()
, nhưng, nếu được cung cấp một Tệp có tên tệp có định dạng DOS 8.3 trên Windows, chẳng hạn như java.io.tmpdir
trả về thuộc tính Hệ thống, thì phương thức này sẽ trả về tên tệp "đầy đủ".
Path.toAbsolutePath().normalize()
đó là một nền tảng tốt giữa con đường chính tắc (thực tế) và con đường tuyệt đối một mình.