Как преобразовать относительный путь в абсолютный путь в приложении Windows?

92

Как преобразовать относительный путь в абсолютный путь в приложении Windows?

Я знаю, что мы можем использовать server.MapPath () в ASP.NET. Но что мы можем делать в приложении Windows?

Я имею в виду, если есть встроенная функция .NET, которая может справиться с этим ...

Амит Дхалл
источник
2
Вы имеете в виду относительный путь к текущему каталогу, другими словами к рабочему каталогу, или относительно местоположения .exe?
Тобиас Херткорн,
2
Есть два вида относительных путей. Один if имеет форму «A \ B \ C» и не подразумевает определенной базы. Другой имеет форму «. \ A \ B» или «.. \ A \ B»; они относятся к текущему рабочему каталогу.
MSalters,
1
@Amit Dhall: Кстати, хорошо принимать и голосовать за ответы, которые вам помогут.
Фрэнсис Б.

Ответы:

184

Ты пробовала:

string absolute = Path.GetFullPath(relative);

? Обратите внимание, что при этом будет использоваться текущий рабочий каталог процесса, а не каталог, содержащий исполняемый файл. Если это не помогает, поясните, пожалуйста, свой вопрос.

Джон Скит
источник
4
Разве это не будет зависеть от того, откуда вы запускаете приложение, независимо от того, где находится exe? Конечно, вопрос по этому поводу не совсем ясен.
Тобиас Херткорн,
1
Как вы говорите, вопрос непонятный. GetFullPath будет разрешен из текущего рабочего каталога. Я отредактирую свой ответ, чтобы указать это.
Джон Скит,
1
Если приложение запускается через проводник Windows, кажется, что текущий каталог и каталог исполняемой сборки одинаковы (по крайней мере, пока что-то не будет сделано, чтобы сделать их разными). Это верно, даже если вы используете ярлык для исполняемого файла, где ярлык находится в совершенно другом месте.
H2ONaCl
19

Если вы хотите получить путь относительно вашего .exe, используйте

string absolute = Path.Combine(Application.ExecutablePath, relative);
Тобиас Херткорн
источник
4
Только будьте осторожны с Path.Combine. Если «относительная» часть начинается с косой черты, она может не делать того, что вы думаете.
Noon Silk,
2
@silky: ну тогда это не относительное, не так ли?
Тор Хауген,
1
Кажется, Path.Combineдаже не может обрабатывать пути, относящиеся к дисководу. Кажется, он просто игнорирует начальный путь. Я публикую свое полное решение.
Nyerguds 05
3
Это не может обрабатывать относительный путь. Он принимает только каталог и имя файла. Если второй аргумент начинается с чего-то подобного .., это приведет к мусору.
Джонатан Вуд
1
@JonathanWood На самом деле, этот "мусор" (пути, которые ..в них включены ) прекрасно принимается и разрешается всеми системами обработки файлов в .Net. Если вас это беспокоит, казните absolute = Path.GetFullPath(absolute).
Nyerguds
15

Этот работает для путей на разных дисках, для относительных путей и для фактических относительных путей. Черт возьми, это даже работает, если на basePathсамом деле не абсолютное; он всегда использует текущий рабочий каталог как последний резерв.

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
Отличное решение, потому что оно объединяет абсолютный или родственный путь в соответствии с базовым путем. На мой взгляд, аргумент relativePath следует переименовать в AbsoluteOrRelativePath, поскольку это то, что он действительно представляет. Спасибо
Хулио Нобре
1
Что ж, если это уже абсолютный путь, это просто особый случай, на самом деле ... функция по-прежнему предназначена для разрешения относительных путей, лол. Я просто назвал это здесь, чтобы прояснить, какой параметр есть какой;)
Nyerguds
1
@JulioNobre, тем более что здесь аргументы перевернуты по сравнению с Path.Combine. Это легко исправить, но я избегаю этого, так как я часто использую его для разрешения относительных путей в рабочем каталоге и присвоение null в качестве первого аргумента выглядит странно.
Nyerguds
1
Я ценю ваш совет, но я намерен использовать этот помощник только тогда, когда мне нужно объединить базовый путь с другим путем, который может быть либо относительно этого базового пути, либо абсолютным. Вот почему я предпочел использовать следующую подпись: GetAbsolutePath (String BasePath, String RelativeOrAbsolutePath). Если какой-либо аргумент имеет значение null, возникает исключение, чтобы подтвердить, что оба являются обязательными для использования этого метода. Еще раз спасибо :-)
Julio Nobre
2
Да, это разумно. Но не стоит редактировать это просто для того, чтобы подтасовывать какие-то аргументы.
Nyerguds
1

Это немного более старая тема, но может быть кому-то полезна. Я решил аналогичную проблему, но в моем случае путь не был в начале текста.

Итак, вот мое решение:

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

Пример:

Data Source=.\Data\Data.sdf;Persist Security Info=False;
Data Source=..\..\bin\Debug\Data\Data.sdf;Persist Security Info=False;
Веси
источник
1
Гм. Вы изобретаете велосипед. Path.GetFullPathразрешает. \ и .. \ автоматически. Кроме того, вы добавляете AbsolutePathфункцию расширения в класс String в целом ... может быть немного излишним.
Nyerguds
1
Я ошибаюсь, говоря, что Path.GetFullPath всегда считает базовый каталог текущим каталогом AppDomain приложения. В этом случае Path.GetFullPath не может вернуть полный путь из другого каталога. Однако следующий алгоритм учитывает это ... Я имею в виду, что вам просто нужно добавить еще один необязательный параметр, который будет заменой CurrentDomainDirectory.
Самуэль