Làm thế nào để chuyển đổi một đường dẫn tương đối thành một đường dẫn tuyệt đối trong ứng dụng Windows?


90

Làm cách nào để chuyển đổi đường dẫn tương đối thành đường dẫn tuyệt đối trong ứng dụng Windows?

Tôi biết chúng ta có thể sử dụng server.MapPath () trong ASP.NET. Nhưng chúng ta có thể làm gì trong một ứng dụng Windows?

Ý tôi là, nếu có một hàm tích hợp .NET có thể xử lý điều đó ...


2
Ý của bạn là một đường dẫn liên quan đến thư mục hiện tại, nói cách khác là thư mục đang làm việc, hoặc liên quan đến vị trí của .exe?
— Tobias Hertkorn 09/09/09

2
Có hai loại đường dẫn tương đối. Một if có dạng "A \ B \ C" và không ngụ ý một cơ sở cụ thể. Cái kia có dạng ". \ A \ B" hoặc ".. \ A \ B"; chúng liên quan đến thư mục làm việc hiện tại.
— MSalters 09/09/09

1
@Amit Dhall: Nhân tiện, việc chấp nhận và tán thành (các) câu trả lời giúp ích cho bạn là điều tốt.
— Francis B.

Câu trả lời:


183

Bạn đã thử chưa:

string absolute = Path.GetFullPath(relative);

? Lưu ý rằng điều đó sẽ sử dụng thư mục làm việc hiện tại của tiến trình, không phải thư mục chứa tệp thực thi. Nếu điều đó không hữu ích, vui lòng làm rõ câu hỏi của bạn.


4
Điều đó sẽ không phụ thuộc vào nơi bạn bắt đầu ứng dụng, không phụ thuộc vào nơi đặt exe? Cho rằng câu hỏi không thực sự rõ ràng về điều đó.
— Tobias Hertkorn 09/09/09

1
Như bạn nói, câu hỏi không rõ ràng. GetFullPath sẽ giải quyết từ thư mục làm việc hiện tại. Tôi sẽ chỉnh sửa câu trả lời của mình để chỉ ra điều này.
— Jon Skeet 09/09/09

1
Nếu một ứng dụng được khởi động thông qua Windows Explorer thì có vẻ như thư mục hiện tại và thư mục lắp ráp đang thực thi giống nhau (ít nhất là cho đến khi hoàn thành một số việc để làm cho chúng khác nhau). Điều này đúng ngay cả khi bạn sử dụng một đoạn ngắn cho tệp thực thi nơi đoạn ngắn nằm ở một nơi hoàn toàn khác.
— H2ONaCl

19

Nếu bạn muốn lấy đường dẫn liên quan đến .exe của mình thì hãy sử dụng

string absolute = Path.Combine(Application.ExecutablePath, relative);

4
Chỉ cần cẩn thận với Path.Combine. Nếu phần 'tương đối' bắt đầu bằng dấu gạch chéo, nó có thể không làm như bạn nghĩ.
— Noon Silk

2
@silky: vậy thì nó không phải là tương đối phải không?
— Tor Haugen 09/09/09

1
Có vẻ như Path.Combinethậm chí không thể xử lý các đường dẫn liên quan đến ổ đĩa. Nó chỉ bỏ qua con đường ban đầu có vẻ như. Tôi đang đăng giải pháp đầy đủ của riêng tôi.
— Nyerguds

3
Điều này không thể xử lý một đường dẫn tương đối. Nó chỉ chấp nhận một thư mục và một tên tệp. Nếu đối số thứ hai bắt đầu bằng bất kỳ thứ gì như thế .., nó sẽ tạo ra rác.
— Jonathan Wood

1
@JonathanWood Trên thực tế, "rác" đó (các đường dẫn bao gồm ..chúng) hoàn toàn được chấp nhận và giải quyết bởi tất cả các hệ thống thao tác tệp trong .Net. Nếu nó làm phiền bạn, hãy thực thi absolute = Path.GetFullPath(absolute)nó.
— Nyerguds

15

Cái này hoạt động cho các đường dẫn trên các ổ đĩa khác nhau, cho các đường dẫn tương đối với ổ đĩa và các đường dẫn tương đối thực tế. Heck, nó thậm chí hoạt động nếu basePathkhông thực sự tuyệt đối; nó luôn sử dụng thư mục làm việc hiện tại làm dự phòng cuối cùng.

public static String GetAbsolutePath(String path)
{
    return GetAbsolutePath(null, path);
}

public static String GetAbsolutePath(String basePath, String path)
{
    if (path == null)
        return null;
    if (basePath == null)
        basePath = Path.GetFullPath("."); // quick way of getting current working directory
    else
        basePath = GetAbsolutePath(null, basePath); // to be REALLY sure ;)
    String finalPath;
    // specific for windows paths starting on \ - they need the drive added to them.
    // I constructed this piece like this for possible Mono support.
    if (!Path.IsPathRooted(path) || "\\".Equals(Path.GetPathRoot(path)))
    {
        if (path.StartsWith(Path.DirectorySeparatorChar.ToString()))
            finalPath = Path.Combine(Path.GetPathRoot(basePath), path.TrimStart(Path.DirectorySeparatorChar));
        else
            finalPath = Path.Combine(basePath, path);
    }
    else
        finalPath = path;
    // resolves any internal "..\" to get the true full path.
    return Path.GetFullPath(finalPath);
}

1
Giải pháp tuyệt vời vì nó kết hợp cả đường dẫn tuyệt đối hoặc họ hàng theo đường dẫn cơ sở. Theo ý kiến ​​của tôi, đối số relativePath nên được đổi tên thành AbsoluteOrRelativePath, vì nó là những gì nó thực sự đại diện. Cảm ơn
— Julio Nobre.

1
Chà, nếu nó đã là một đường dẫn tuyệt đối, thì đó chỉ là một trường hợp đặc biệt, thực sự ... chức năng này vẫn dùng để giải quyết các đường dẫn tương đối, lol. Tôi chỉ đặt tên cho nó ở đây để làm rõ đó là thông số nào;)
— Nyerguds

1
@JulioNobre đặc biệt vì args ở đây được đảo ngược so với Path.Combine. Điều đó dễ dàng được sửa chữa, nhưng tôi tránh nó vì tôi thường sử dụng nó để giải quyết các đường dẫn tương đối trên thư mục làm việc và đưa ra null như đối số đầu tiên trông kỳ lạ.
— Nyerguds

1
Tôi đánh giá cao lời khuyên của bạn, nhưng tôi chỉ có ý định sử dụng trình trợ giúp này khi tôi cần kết hợp một đường dẫn cơ sở với một đường dẫn khác có thể liên quan đến đường dẫn cơ sở đó hoặc tuyệt đối. Đó là lý do tại sao tôi muốn sử dụng chữ ký sau: GetAbsolutePath (String BasePath, String RelativeOrAbsolutePath). Nếu một số đối số là rỗng, một ngoại lệ được đưa ra để củng cố rằng cả hai đều bắt buộc phải sử dụng phương pháp này. Một lần nữa, cảm ơn :-)
— Julio Nobre,

2
Vâng, điều đó hợp lý. Tuy nhiên, bạn không thể bận tâm khi chỉnh sửa điều này chỉ để tung hứng một số args xung quanh.
— Nyerguds

1

Đó là một chủ đề cũ hơn một chút, nhưng nó có thể hữu ích cho ai đó. Tôi đã giải quyết một vấn đề tương tự, nhưng trong trường hợp của tôi, đường dẫn không nằm ở đầu văn bản.

Vì vậy, đây là giải pháp của tôi:

public static class StringExtension
{
    private const string parentSymbol = "..\\";
    private const string absoluteSymbol = ".\\";
    public static String AbsolutePath(this string relativePath)
    {
        string replacePath = AppDomain.CurrentDomain.BaseDirectory;
        int parentStart = relativePath.IndexOf(parentSymbol);
        int absoluteStart = relativePath.IndexOf(absoluteSymbol);
        if (parentStart >= 0)
        {
            int parentLength = 0;
            while (relativePath.Substring(parentStart + parentLength).Contains(parentSymbol))
            {
                replacePath = new DirectoryInfo(replacePath).Parent.FullName;
                parentLength = parentLength + parentSymbol.Length;
            };
            relativePath = relativePath.Replace(relativePath.Substring(parentStart, parentLength), string.Format("{0}\\", replacePath));
        }
        else if (absoluteStart >= 0)
        {
            relativePath = relativePath.Replace(".\\", replacePath);
        }
        return relativePath;
    }
}

Thí dụ:

Data Source=.\Data\Data.sdf;Persist Security Info=False;
Data Source=..\..\bin\Debug\Data\Data.sdf;Persist Security Info=False;

1
Ừm. Bạn đang phát minh lại bánh xe. Path.GetFullPathtự động giải quyết. \ và .. \. Ngoài ra, bạn đang thêm AbsolutePathchức năng mở rộng vào lớp String nói chung ... có thể hơi quá mức cần thiết.
— Nyerguds

1
Tôi có sai khi nói rằng Path.GetFullPath luôn coi thư mục cơ sở là thư mục hiện tại của AppDomain của ứng dụng. Trong trường hợp này, Path.GetFullPath không thể trả về đường dẫn đầy đủ từ một thư mục khác. Tuy nhiên, thuật toán sau sẽ xem xét điều này ... Ý tôi là, bạn chỉ cần thêm một tham số tùy chọn khác sẽ thay thế cho CurrentDomainDirectory.
— Samuel
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 cookie và Chính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.