/// <summary> /// This helper method can be used to convert a relative path to an absolute path based on the given base /// path. /// </summary> /// <param name="basePath">The base path</param> /// <param name="relativePath">A relative path</param> /// <returns>An absolute path</returns> /// <remarks>If the base path is null or empty, the current working folder is used.</remarks> /// <example> /// <code lang="cs"> /// string basePath = @"E:\DotNet\CS\TestProject\Source"; /// string relativePath = @"..\Doc\Help.html"; /// /// string absolutePath = FilePath.RelativeToAbsolutePath(basePath, /// relativePath); /// /// Console.WriteLine(absolutePath); /// /// // Results in: E:\DotNet\CS\TestProject\Doc\Help.html /// </code> /// <code lang="vbnet"> /// Dim basePath As String = "E:\DotNet\CS\TestProject\Source" /// Dim relativePath As String = "..\Doc\Help.html" /// /// Dim absolutePath As String = _ /// FilePath.RelativeToAbsolutePath(basePath, relativePath); /// /// Console.WriteLine(absolutePath) /// /// ' Results in: E:\DotNet\CS\TestProject\Doc\Help.html /// </code> /// </example> public static string RelativeToAbsolutePath(string basePath, string relativePath) { int idx; // If blank return the base path if (String.IsNullOrEmpty(relativePath)) { return(basePath); } // Don't bother if already absolute if (IOPath.IsPathRooted(relativePath)) { return(relativePath); } // If not specified, use the current folder as the base path if (basePath == null || basePath.Trim().Length == 0) { basePath = Directory.GetCurrentDirectory(); } else { basePath = IOPath.GetFullPath(basePath); } // Remove trailing backslashes for comparison if (FolderPath.IsPathTerminated(basePath)) { basePath = basePath.Substring(0, basePath.Length - 1); } if (relativePath == ".") { relativePath = String.Empty; } // Remove ".\" or "./" if it's there if (relativePath.Length > 1 && relativePath[0] == '.' && (relativePath[1] == IOPath.DirectorySeparatorChar || relativePath[1] == IOPath.AltDirectorySeparatorChar)) { relativePath = relativePath.Substring(2); } // Split the paths into their component parts string[] baseParts = basePath.Split(IOPath.DirectorySeparatorChar); string[] relParts = relativePath.Split(IOPath.DirectorySeparatorChar); // Figure out how far to move up from the relative path for (idx = 0; idx < relParts.Length; ++idx) { if (relParts[idx] != "..") { break; } } // If it's below the base path, just add it to the base path if (idx == 0) { return(FilePath.GetFullPath(basePath + IOPath.DirectorySeparatorChar + relativePath)); } string absPath = String.Join(IOPath.DirectorySeparatorChar.ToString(), baseParts, 0, Math.Max(0, baseParts.Length - idx)); absPath += IOPath.DirectorySeparatorChar + String.Join(IOPath.DirectorySeparatorChar.ToString(), relParts, idx, relParts.Length - idx); return(FilePath.GetFullPath(absPath)); }
/// <summary> /// This helper method can be used to convert an absolute path to one that is relative to the given base /// path. /// </summary> /// <param name="basePath">The base path</param> /// <param name="absolutePath">An absolute path</param> /// <returns>A path to the given absolute path that is relative to the given base path</returns> /// <remarks>If the base path is null or empty, the current working folder is used.</remarks> /// <example> /// <code lang="cs"> /// string basePath = @"E:\DotNet\CS\TestProject\Source"; /// string absolutePath = @"E:\DotNet\CS\TestProject\Doc\Help.html"; /// /// string relativePath = FilePath.AbsoluteToRelativePath(basePath, /// absolutePath); /// /// Console.WriteLine(relativePath); /// /// // Results in: ..\Doc\Help.html /// </code> /// <code lang="vbnet"> /// Dim basePath As String = "E:\DotNet\CS\TestProject\Source" /// Dim absolutePath As String = "E:\DotNet\CS\TestProject\Doc\Help.html" /// /// Dim relativePath As String = _ /// FilePath.AbsoluteToRelativePath(basePath, absolutePath); /// /// Console.WriteLine(relativePath) /// /// ' Results in: ..\Doc\Help.html /// </code> /// </example> public static string AbsoluteToRelativePath(string basePath, string absolutePath) { bool hasBackslash = false; string relPath; int minLength, idx; // If not specified, use the current folder as the base path if (basePath == null || basePath.Trim().Length == 0) { basePath = Directory.GetCurrentDirectory(); } else { basePath = IOPath.GetFullPath(basePath); } if (absolutePath == null) { absolutePath = String.Empty; } // Just in case, make sure the path is absolute if (!IOPath.IsPathRooted(absolutePath)) { absolutePath = FilePath.GetFullPath(absolutePath); } // Remove trailing backslashes for comparison if (FolderPath.IsPathTerminated(basePath)) { basePath = basePath.Substring(0, basePath.Length - 1); } if (FolderPath.IsPathTerminated(absolutePath)) { absolutePath = absolutePath.Substring(0, absolutePath.Length - 1); hasBackslash = true; } // Split the paths into their component parts char[] separators = { IOPath.DirectorySeparatorChar, IOPath.AltDirectorySeparatorChar, IOPath.VolumeSeparatorChar }; string[] baseParts = basePath.Split(separators); string[] absParts = absolutePath.Split(separators); // Find the common base path minLength = Math.Min(baseParts.Length, absParts.Length); for (idx = 0; idx < minLength; idx++) { if (String.Compare(baseParts[idx], absParts[idx], StringComparison.OrdinalIgnoreCase) != 0) { break; } } // Use the absolute path if there's nothing in common (i.e. they are on different drives or network // shares. if (idx == 0) { relPath = absolutePath; } else { // If equal to the base path, it doesn't have to go anywhere. Otherwise, work up from the base // path to the common root. if (idx == baseParts.Length) { relPath = String.Empty; } else { relPath = new String(' ', baseParts.Length - idx).Replace(" ", ".." + IOPath.DirectorySeparatorChar); } // And finally, add the path from the common root to the absolute path relPath += String.Join(IOPath.DirectorySeparatorChar.ToString(), absParts, idx, absParts.Length - idx); } return((hasBackslash) ? FolderPath.TerminatePath(relPath) : relPath); }