Jak przekonwertować ścieżkę względną na ścieżkę bezwzględną w aplikacji systemu Windows?


90

Jak przekonwertować ścieżkę względną na ścieżkę bezwzględną w aplikacji systemu Windows?

Wiem, że możemy użyć server.MapPath () w ASP.NET. Ale co możemy zrobić w aplikacji Windows?

Mam na myśli, jeśli istnieje wbudowana funkcja .NET, która może to obsłużyć ...


2
Czy masz na myśli względną ścieżkę do bieżącego katalogu, innymi słowy do katalogu roboczego, czy względną do lokalizacji pliku .exe?
Tobias Hertkorn

2
Istnieją dwa rodzaje ścieżek względnych. Jeden jeśli ma postać „A \ B \ C” i nie oznacza konkretnej podstawy. Drugi ma postać „. \ A \ B” lub „.. \ A \ B”; są one względne w stosunku do bieżącego katalogu roboczego.
MSalters

1
@Amit Dhall: Nawiasem mówiąc, dobrze jest zaakceptować i zagłosować za odpowiedzi, które są pomocne.
Francis B.,

Odpowiedzi:


183

Czy próbowałeś:

string absolute = Path.GetFullPath(relative);

? Zauważ, że użyje to bieżącego katalogu roboczego procesu, a nie katalogu zawierającego plik wykonywalny. Jeśli to nie pomoże, wyjaśnij swoje pytanie.


4
Czy nie zależałoby to od tego, skąd uruchomisz aplikację, a nie od tego, gdzie znajduje się exe? To prawda, że ​​nie jest to do końca jasne.
Tobias Hertkorn

1
Jak mówisz, pytanie nie jest jasne. GetFullPath zostanie rozwiązany z bieżącego katalogu roboczego. Zmienię swoją odpowiedź, aby to zaznaczyć.
Jon Skeet

1
Jeśli aplikacja jest uruchamiana za pomocą Eksploratora Windows, wygląda na to, że katalog bieżący i katalog wykonywania asemblera są takie same (przynajmniej do czasu, gdy zostanie zrobione coś, aby je zmienić). Dzieje się tak, nawet jeśli używasz skrótu do pliku wykonywalnego, w którym skrót znajduje się w zupełnie innym miejscu.
H2ONaCl

19

Jeśli chcesz uzyskać ścieżkę względną do pliku .exe, użyj

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

4
Po prostu uważaj na Path.Combine. Jeśli „względna” część zaczyna się od ukośnika, może nie działać tak, jak myślisz.
Noon Silk

2
@silky: cóż, więc to nie jest względne, prawda?
Tor Haugen

1
Wydaje się, Path.Combineże nie obsługuje nawet ścieżek zależnych od dysku. Po prostu ignoruje początkową ścieżkę, którą się wydaje. Publikuję własne pełne rozwiązanie.
Nyerguds,

3
To nie może obsłużyć ścieżki względnej. Akceptuje tylko katalog i nazwę pliku. Jeśli drugi argument zaczyna się od czegoś podobnego .., przyniesie śmieci.
Jonathan Wood

1
@JonathanWood Właściwie to „śmieci” (ścieżki, które się ..w nich zawierają) są doskonale akceptowane i rozwiązywane przez wszystkie systemy manipulacji plikami w .Net. Jeśli ci to przeszkadza, wykonaj absolute = Path.GetFullPath(absolute)na nim.
Nyerguds

15

Ten działa dla ścieżek na różnych dyskach, dla ścieżek względem dysku i dla rzeczywistych ścieżek względnych. Heck, to działa nawet, jeśli basePathnie jest w rzeczywistości absolutne; zawsze używa bieżącego katalogu roboczego jako ostatecznej rezerwy.

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
Świetne rozwiązanie, ponieważ łączy ścieżkę absolutną lub krewną zgodnie ze ścieżką bazową. Moim zdaniem nazwa argumentu RelativePath powinna zostać zmieniona na AbsoluteOrRelativePath, ponieważ tak naprawdę reprezentuje. Dzięki
Julio Nobre

1
Cóż, jeśli jest to już ścieżka absolutna, to jest to tylko specjalny przypadek, naprawdę ... funkcja nadal jest przeznaczona do rozwiązywania ścieżek względnych, lol. Właśnie nazwałem to tutaj, aby wyjaśnić, który parametr jest który;)
Nyerguds

1
@JulioNobre, zwłaszcza że argumenty tutaj są odwrócone w porównaniu z Path.Combine. Łatwo to naprawić, ale unikam tego, ponieważ często używam go do rozwiązywania ścieżek względnych w katalogu roboczym, a podanie wartości null jako pierwszego argumentu wygląda dziwnie.
Nyerguds

1
Doceniam twoją radę, ale zamierzam użyć tego pomocnika tylko wtedy, gdy muszę połączyć ścieżkę podstawową z inną ścieżką, która może być względna lub bezwzględna. Dlatego wolałem przyjąć następujący podpis: GetAbsolutePath (String BasePath, String RelativeOrAbsolutePath). Jeśli jakiś argument ma wartość null, zgłaszany jest wyjątek, aby potwierdzić, że oba są obowiązkowe, aby użyć tej metody. Jeszcze raz dziękuję :-)
Julio Nobre

2
Tak, to rozsądne. Nie można jednak zawracać sobie głowy edycją tego, aby żonglować niektórymi kłótniami.
Nyerguds

1

To trochę starszy temat, ale może się komuś przydać. Rozwiązałem podobny problem, ale w moim przypadku ścieżka nie była na początku tekstu.

Oto moje rozwiązanie:

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

Przykład:

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

1
Um. Odkrywasz na nowo koło. Path.GetFullPathrozwiązuje. \ i .. \ automatycznie. Ponadto, AbsolutePathogólnie dodajesz funkcję rozszerzającą do klasy String ... może to być trochę przesada.
Nyerguds,

1
Czy mylę się, mówiąc, że Path.GetFullPath zawsze traktuje katalog podstawowy jako katalog bieżący domeny AppDomain aplikacji. W takim przypadku Path.GetFullPath nie może zwrócić pełnej ścieżki z innego katalogu. Poniższy algorytm bierze to jednak pod uwagę ... Mam na myśli, że wystarczy dodać kolejny opcjonalny parametr, który zastąpiłby katalog CurrentDomainDirectory.
Samuel
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.