2009-03-26 26 views
11

thể trùng lặp:
Best way to determine if two path reference to same file in C/C++Normalize với WinAPI

Với hai chuỗi đường dẫn tập tin với vỏ có khả năng khác nhau và dấu gạch chéo ('\' vs '/'), là có một cách nhanh chóng (mà không liên quan đến việc viết chức năng của riêng tôi) để bình thường hóa cả hai đường dẫn đến cùng một biểu mẫu, hoặc ít nhất là để kiểm tra chúng tương đương?

Tôi bị hạn chế đối với WinAPI và C++ chuẩn. Tất cả các tệp đều là cục bộ.

Trả lời

4

Tùy thuộc vào việc đường dẫn có thể là tương đối hay chứa ".." hoặc điểm giao nhau hoặc đường dẫn UNC có thể khó khăn hơn bạn nghĩ. Cách tốt nhất có thể là sử dụng chức năng GetFileInformationByHandle() như trong this answer.

Chỉnh sửa: Tôi đồng ý với nhận xét của RBerteig rằng điều này có thể trở nên khó thực hiện nếu đường dẫn không trỏ đến tệp cục bộ. Bất kỳ bình luận về cách xử lý một cách an toàn trường hợp này sẽ được đánh giá rất nhiều.

+0

Miễn là hai đường dẫn giải quyết các tệp trên cùng một máy tính, thì có vẻ như GetFileInformationByHandle() là câu trả lời đúng.Nếu họ giải quyết cho các máy tính khác nhau, tôi không thấy bảo đảm, và tôi cũng không thấy một cách nhỏ nhặt để có được một máy tính. Nó không nhất thiết phải dễ dàng để thử nghiệm cho điều này. – RBerteig

+0

Tất cả các tệp đều là cục bộ trong trường hợp của tôi, do đó, công trình này hoạt động. –

+0

@RBerteig: Tôi không thấy một cách tầm thường để có được một. Nhưng tôi đã tìm thấy một điều rất không tầm thường và đặt nó vào một câu trả lời; hãy xem. Ngay cả cái đó hầu như chỉ đơn giản là dễ dàng, nhưng nó phải là quá đủ cho hầu hết mọi người. – steveha

3

Có những trường hợp lạ. Ví dụ: "c: \ windows .. \ data \ myfile.txt" giống với "c: \ data. \ Myfile.txt" và "c: \ data \ myfile.txt". Bạn có thể có bất kỳ số "\. \" Và "\ .. \" trong đó. Bạn có thể xem xét chức năng API của Windows GetFullPathName. Nó có thể làm canonicalization cho bạn.

6

Tôi có thể đề xuất PathCanonicalize?

+0

Nó không giống như địa chỉ giao điểm hoặc đường dẫn UNC ... nhưng nó có vẻ hữu ích để biết về. – RBerteig

+0

Đó là phương pháp tôi đang tìm kiếm. Không GetFullPathName. –

+6

Sau khi xem câu trả lời này, tôi đã thử sử dụng PathCanonicalize() và phát hiện ra rằng nó đã bị phá vỡ khủng khiếp. 'PathCanonicalize (" ../ foo.txt ")' luôn trả về '/ foo.txt'! PathCanonicalize() chỉ thực hiện chỉnh sửa tầm thường trên chuỗi, và sự phá vỡ ở trên là hành vi được ghi lại. Vô ích. Tôi sẽ đăng một câu trả lời khác với những gì tôi tìm thấy. – steveha

6

Tôi đã tìm thấy một bài đăng trên blog với chức năng kỹ lưỡng, thậm chí phức tạp nhất mà tôi từng thấy để giải quyết vấn đề này. Nó xử lý mọi thứ, thậm chí là các trường hợp góc kinh khủng như V:foo.txt nơi bạn sử dụng lệnh subst để ánh xạ V: đến Z: nhưng bạn đã sử dụng subst để ánh xạ Z: tới một số ổ đĩa khác; nó lặp lại cho đến khi tất cả các lệnh subst được bỏ qua. URL:

http://pdh11.blogspot.com/2009/05/pathcanonicalize-versus-what-it-says-on.html

Dự án của tôi là mã C tinh khiết, và chức năng đó là C++. Tôi bắt đầu dịch nó, nhưng sau đó tôi đã tìm ra rằng tôi có thể nhận được đường dẫn chuẩn hóa mà tôi muốn với một hàm gọi: GetLongPathName(). Điều này sẽ không xử lý các trường hợp góc khủng khiếp, nhưng nó xử lý các nhu cầu trước mắt của tôi.

tôi phát hiện ra rằng GetLongPathName("foo.txt") chỉ trả foo.txt, nhưng chỉ bằng cách thêm vào trước ./ vào tên tập tin tôi đã mở rộng mẫu bình thường:

GetLongPathName("./foo.txt"), nếu thực hiện trong thư mục C:\Users\steveha, trả C:\Users\steveha\foo.txt.

Vì vậy, trong giả:

nếu char thứ hai của tên đường dẫn được ':' hoặc char đầu tiên là '/' hoặc '\', chỉ cần gọi GetLongPathName() khác, sao chép "./" vào một bộ đệm tạm thời, sau đó sao chép tên tệp thành bộ đệm tạm thời + 2, để lấy một bản sao của tên tệp được thêm vào với "./" và sau đó gọi GetLongPathName().

+0

Vâng, ít nhất bài đăng đó cung cấp mã trông giống như tất cả việc nâng hạng nặng. Nó chắc chắn xử lý nhiều trường hợp góc hơn và hoàn toàn hơn mà bạn mong đợi. Rõ ràng tác giả đã đốt cháy các vấn đề này một vài lần ... Dự phòng đơn giản của bạn có thể đủ tốt cho hầu hết các trường hợp và cho phép các trường hợp lạ được sử dụng để đánh lừa phần mềm cần lừa đảo. – RBerteig

+0

Người dùng của tôi có thể chưa bao giờ nghe đến lệnh 'subst' và mã C đơn giản của tôi đã hoạt động hoàn hảo cho đến nay. – steveha

+0

sự bất ngờ lớn đối với chúng tôi là bộ đếm thời gian cũ là 'subst' vẫn còn tồn tại ... nó thậm chí còn có mặt trong Win7 64bit, nhưng nó có ngày trở lại DOS 5.0 nếu không sớm hơn. Win7 đi kèm với một loạt các JUNCTIONS cho khả năng tương thích ngược. Đó là cho một số kịch bản Perl cũ của tôi đi lang thang qua hệ thống tập tin phù hợp vì chúng không hoàn toàn là thư mục và chắc chắn không phải là tập tin. Một ví dụ là 'C: \ Documents and Settings' là một JUNCTION được ánh xạ tới' C: \ Users'. – RBerteig

Các vấn đề liên quan