Bagaimana cara mengonversi jalur relatif ke jalur absolut dalam aplikasi Windows?


90

Bagaimana cara mengonversi jalur relatif ke jalur absolut dalam aplikasi Windows?

Saya tahu kita bisa menggunakan server.MapPath () di ASP.NET. Tapi apa yang bisa kita lakukan di aplikasi Windows?

Maksud saya, jika ada fungsi bawaan .NET yang dapat menangani itu ...


2
Apakah yang Anda maksud adalah jalur relatif ke direktori saat ini, dengan kata lain direktori kerja, atau relatif terhadap lokasi .exe?
Tobias Hertkorn

2
Ada dua jenis jalan relatif. Satu jika dalam bentuk "A \ B \ C" dan tidak menyiratkan basis tertentu. Yang lainnya memiliki bentuk ". \ A \ B" atau ".. \ A \ B"; itu relatif terhadap direktori kerja saat ini.
MSalters

1
@Amit Dhall: Ngomong-ngomong, adalah hal yang baik untuk menerima dan mendukung jawaban yang membantu Anda.
Francis B.

Jawaban:


183

Sudahkah Anda mencoba:

string absolute = Path.GetFullPath(relative);

? Perhatikan bahwa itu akan menggunakan direktori kerja saat ini dari proses tersebut, bukan direktori yang berisi file yang dapat dieksekusi. Jika itu tidak membantu, klarifikasi pertanyaan Anda.


4
Bukankah itu tergantung di mana Anda memulai aplikasi, tidak tergantung di mana exe itu berada? Memang pertanyaannya tidak terlalu jelas tentang itu.
Tobias Hertkorn

1
Seperti yang Anda katakan, pertanyaannya tidak jelas. GetFullPath akan menyelesaikan dari direktori kerja saat ini. Saya akan mengedit tanggapan saya untuk menunjukkan ini.
Jon Skeet

1
Jika aplikasi dijalankan melalui Windows Explorer, tampaknya direktori saat ini dan direktori rakitan pelaksana adalah sama (setidaknya hingga sesuatu dilakukan untuk membuatnya berbeda). Ini benar bahkan jika Anda menggunakan jalan pintas ke eksekusi di mana jalan pintas berada di tempat yang sama sekali berbeda.
H2ONaCl

19

Jika Anda ingin mendapatkan jalur relatif terhadap .exe Anda, gunakan

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

4
Berhati-hatilah dengan Path.Combine. Jika bagian 'relatif' dimulai dengan garis miring, itu mungkin tidak melakukan apa yang Anda pikirkan.
Noon Silk

2
@silky: yah, kalau begitu itu tidak relatif, kan?
Tor Haugen

1
Tampaknya Path.Combinebahkan tidak bisa menangani jalur drive-relative. Tampaknya hanya mengabaikan jalur awal. Saya memposting solusi lengkap saya sendiri.
Nyerguds

3
Ini tidak dapat menangani jalur relatif. Ini hanya menerima direktori dan nama file. Jika argumen kedua dimulai dengan sesuatu seperti ..itu, itu akan menghasilkan sampah.
Jonathan Wood

1
@JonathanWood Sebenarnya, "sampah" (jalur yang termasuk ..di dalamnya) diterima dengan sempurna dan diselesaikan oleh semua sistem manipulasi file di .Net. Jika itu mengganggu Anda, jalankan absolute = Path.GetFullPath(absolute).
Nyerguds

15

Yang ini berfungsi untuk jalur pada drive yang berbeda, untuk jalur drive-relatif dan untuk jalur relatif aktual. Heck, itu bahkan berhasil jika basePathtidak benar-benar mutlak; itu selalu menggunakan direktori kerja saat ini sebagai fallback terakhir.

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
Solusi hebat karena menggabungkan jalur absolut atau kerabat menurut jalur dasar. Menurut pendapat saya, argumen relativePath harus diganti namanya menjadi AbsoluteOrRelativePath, karena itulah yang diwakilinya. Terima kasih
Julio Nobre

1
Nah, kalau itu sudah path absolut, itu hanya kasus khusus, sungguh ... fungsinya masih dimaksudkan untuk menyelesaikan jalur relatif, lol. Saya baru saja menamainya di sini untuk memperjelas parameter mana yang mana;)
Nyerguds

1
@JulioNobre terutama karena argumen di sini terbalik dibandingkan Path.Combine. Itu mudah diperbaiki, tetapi saya menghindarinya karena saya sering menggunakannya untuk menyelesaikan jalur relatif pada direktori kerja, dan memberikan null sebagai argumen pertama terlihat aneh.
Nyerguds

1
Saya menghargai saran Anda, tetapi saya hanya bermaksud menggunakan penolong ini ketika saya perlu menggabungkan jalur dasar dengan jalur lain yang mungkin relatif terhadap jalur dasar tersebut atau absolut. Itu sebabnya saya lebih suka mengadopsi tanda tangan berikut: GetAbsolutePath (String BasePath, String RelativeOrAbsolutePath). Jika beberapa argumen nihil, pengecualian dimunculkan untuk menegaskan bahwa keduanya wajib untuk menggunakan metode ini. Sekali lagi, terima kasih :-)
Julio Nobre

2
Ya, itu masuk akal. Tidak dapat diganggu untuk mengedit ini hanya untuk menyulap beberapa perdebatan.
Nyerguds

1

Ini topik yang sedikit lebih tua, tapi mungkin berguna untuk seseorang. Saya telah memecahkan masalah serupa, tetapi dalam kasus saya, jalurnya tidak berada di awal teks.

Jadi inilah solusi saya:

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;
    }
}

Contoh:

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

1
Um. Anda menciptakan kembali roda. Path.GetFullPathmenyelesaikan. \ dan .. \ secara otomatis. Selain itu, Anda menambahkan AbsolutePathfungsi ekstensi ke kelas String secara umum ... mungkin sedikit berlebihan.
Nyerguds

1
Apakah saya salah mengatakan bahwa Path.GetFullPath selalu menganggap direktori dasar sebagai direktori AppDomain aplikasi saat ini. Dalam kasus ini, Path.GetFullPath tidak dapat mengembalikan jalur lengkap dari direktori yang berbeda. Algoritme berikut, bagaimanapun, mempertimbangkan hal ini ... Maksud saya, Anda hanya perlu menambahkan parameter opsional lain yang akan menggantikan CurrentDomainDirectory.
Samuel
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.