Đường dẫn. Kết hợp tuyệt đối với chuỗi đường dẫn tương đối


94

Tôi đang cố gắng tham gia một đường dẫn Windows với một đường dẫn tương đối bằng cách sử dụng Path.Combine.

Tuy nhiên, Path.Combine(@"C:\blah",@"..\bling")trả về C:\blah\..\blingthay vì C:\bling\.

Có ai biết cách thực hiện điều này mà không cần viết trình giải quyết đường dẫn tương đối của riêng tôi (không quá khó)?



5
Chúng tôi đang nhận được các câu trả lời khác nhau ở đây .. Tôi không nghĩ đó là một bản sao
CVertex

1
nó trùng lặp, mặc dù tôi nghĩ Path.GetFullName là một giải pháp tốt hơn.
Greg Dean

Bạn vừa mâu thuẫn với chính mình. Nhưng cảm ơn vì câu trả lời thay thế.
CVertex

Câu trả lời:


63

Những gì hoạt động:

string relativePath = "..\\bling.txt";
string baseDirectory = "C:\\blah\\";
string absolutePath = Path.GetFullPath(baseDirectory + relativePath);

(kết quả: AbsolPath = "C: \ bling.txt")

Những gì không hoạt động

string relativePath = "..\\bling.txt";
Uri baseAbsoluteUri = new Uri("C:\\blah\\");
string absolutePath = new Uri(baseAbsoluteUri, relativePath).AbsolutePath;

(kết quả: AbsolPath = "C: /blah/bling.txt")


8
Vâng, đó là những gì tôi đang nói bóng gió với bài
Llyle

7
Chỉ cần đảm bảo baseDirectory có dấu \\, nếu không bạn sẽ kết thúc C:\\blah..\\bling.txtvà điều đó không hoạt động. Trong trường hợp đó bạn có thể tự thêm chúng vào chuỗi hoặc làmPath.GetFullPath(Path.Combine(baseDirectory, relativePath))
Nelson tốt đối với

5
Không phải kết quả của phần Tác phẩm của bạn là C:\bling.txtgì?
cod3monk3y

Tại sao phương pháp dựa trên URI không hoạt động? Theo câu trả lời này , kết quả là hợp lệ (và nó dường như cũng được công nhận trên Windows ).
FH

37

Gọi Path.GetFullPath trên đường dẫn kết hợp http://msdn.microsoft.com/en-us/library/system.io.path.getfullpath.aspx

> Path.GetFullPath(Path.Combine(@"C:\blah\",@"..\bling"))
C:\bling

(Tôi đồng ý Path.Combine nên tự làm điều này)


Lưu ý rằng điều này chỉ hoạt động nếu đường dẫn đầu tiên là đường dẫn tuyệt đối. Nó không hoạt động choPath.GetFullPath(Path.Combine(@"..\..\blah",@"\bling"))
derekantrican


4

Đối với các ứng dụng phổ biến của Windows Path.GetFullPath()không khả dụng, bạn có thể sử dụng System.Urilớp thay thế:

 Uri uri = new Uri(Path.Combine(@"C:\blah\",@"..\bling"));
 Console.WriteLine(uri.LocalPath);

3

Điều này sẽ cung cấp cho bạn chính xác những gì bạn cần (đường dẫn KHÔNG phải tồn tại để điều này hoạt động)

DirectoryInfo di = new DirectoryInfo(@"C:\blah\..\bling");
string cleanPath = di.FullName;

1
Cả Path.GetFullPath () và DirectoryInfo.FullName sẽ hoạt động trên một đường dẫn hư cấu. Vấn đề là khi tệp thực sự tồn tại, quá trình thực thi cần FileIOPermission - đúng cho cả hai API. (xem MSDN)
Paul Williams

1

Hãy cẩn thận với Dấu gạch chéo ngược, đừng quên chúng (không sử dụng hai lần :)

string relativePath = "..\\bling.txt";
string baseDirectory = "C:\\blah\\";
//OR:
//string relativePath = "\\..\\bling.txt";
//string baseDirectory = "C:\\blah";
//THEN
string absolutePath = Path.GetFullPath(baseDirectory + relativePath);

0

Path.GetFullPath() không hoạt động với các đường dẫn tương đối.

Đây là giải pháp hoạt động với cả hai đường dẫn tương đối + tuyệt đối. Nó hoạt động trên cả Linux + Windows và nó giữ nguyên ..như mong đợi ở phần đầu của văn bản (ở phần còn lại, chúng sẽ được chuẩn hóa). Giải pháp vẫn dựa vào Path.GetFullPathđể thực hiện sửa chữa với một cách giải quyết nhỏ.

Đó là một phương pháp mở rộng, vì vậy hãy sử dụng nó như text.Canonicalize()

/// <summary>
///     Fixes "../.." etc
/// </summary>
public static string Canonicalize(this string path)
{
    if (path.IsAbsolutePath())
        return Path.GetFullPath(path);
    var fakeRoot = Environment.CurrentDirectory; // Gives us a cross platform full path
    var combined = Path.Combine(fakeRoot, path);
    combined = Path.GetFullPath(combined);
    return combined.RelativeTo(fakeRoot);
}
private static bool IsAbsolutePath(this string path)
{
    if (path == null) throw new ArgumentNullException(nameof(path));
    return
        Path.IsPathRooted(path)
        && !Path.GetPathRoot(path).Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal)
        && !Path.GetPathRoot(path).Equals(Path.AltDirectorySeparatorChar.ToString(), StringComparison.Ordinal);
}
private static string RelativeTo(this string filespec, string folder)
{
    var pathUri = new Uri(filespec);
    // Folders must end in a slash
    if (!folder.EndsWith(Path.DirectorySeparatorChar.ToString())) folder += Path.DirectorySeparatorChar;
    var folderUri = new Uri(folder);
    return Uri.UnescapeDataString(folderUri.MakeRelativeUri(pathUri).ToString()
        .Replace('/', Path.DirectorySeparatorChar));
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.