如何创建和解决相对路径?
我的应用程序打开文件位于执行目录的子目录中,该子目录称为" sample",其中包含文件:
example.raf
(示例扩展名,不重要)background.gif
example.raf包含到background.gif的相对路径(在这种情况下,仅文件名是因为文件与raf处于同一目录),而RAF的打开导致应用程序读取并显示background.gif。
当我使用OpenFileDialog加载RAF文件时,一切正常,图像正确加载。我知道打开文件对话框会以某种方式更改当前工作目录,但是我无法在不调用打开文件对话框的情况下重新创建它
不幸的是,如果我直接从代码中调用raf读取方法,而没有提供文件格式OpenFileDialog
的路径,
LoadRAF("sample\example.raf");
在这种情况下,我遇到了问题,应用尝试从ExecutablePath而不是从包含RAF文件和图像的子目录中加载图像。当然,这是正常行为,但在这种情况下,这是非常不希望的。它需要处理我的应用程序中路径的相对和绝对类型,所以我应该怎么做才能解决这个问题,如何更改ExecutablePath或者至少可以在" OpenFileDialog"的情况下可以做些其他事情来使其正常工作?
解决方案
OpenFileDialog在幕后吐出一条绝对路径。
如果我们知道raf文件的位置,则可以执行以下操作:
string parentPath = Directory.GetParent(rafFilePath); string imagePath = Path.Combine(parentPath, imageFileNameFromRaf);
imagePath现在将包含从raf文件中包含的图像名称以及raf文件所在的目录派生的图像的绝对路径。
我的项目ZipSolution(http://zipsolution.codeplex.com/)的下一个代码
显示了如何在.net中解析和创建相对路径
using System; using System.Collections.Generic; using System.Text; using System.IO; namespace ZipSolution { internal static class RelativePathDiscovery { /// <summary> /// Produces relative path when possible to go from baseLocation to targetLocation /// </summary> /// <param name="baseLocation">The root folder</param> /// <param name="targetLocation">The target folder</param> /// <returns>The relative path relative to baseLocation</returns> /// <exception cref="ArgumentNullException">base or target locations are null or empty</exception> public static string ProduceRelativePath(string baseLocation, string targetLocation) { if (string.IsNullOrEmpty(baseLocation)) { throw new ArgumentNullException("baseLocation"); } if (string.IsNullOrEmpty(targetLocation)) { throw new ArgumentNullException("targetLocation"); } if (!Path.IsPathRooted(baseLocation)) { return baseLocation; } if (!Path.IsPathRooted(targetLocation)) { return targetLocation; } if (string.Compare(Path.GetPathRoot(baseLocation), Path.GetPathRoot(targetLocation), true) != 0) { return targetLocation; } if (string.Compare(baseLocation, targetLocation, true) == 0) { return "."; } string resultPath = "."; if (!targetLocation.EndsWith(@"\")) { targetLocation = targetLocation + @"\"; } if (baseLocation.EndsWith(@"\")) { baseLocation = baseLocation.Substring(0, baseLocation.Length - 1); } while (!targetLocation.StartsWith(baseLocation + @"\", StringComparison.OrdinalIgnoreCase)) { resultPath = resultPath + @"\.."; baseLocation = Path.GetDirectoryName(baseLocation); if (baseLocation.EndsWith(@"\")) { baseLocation = baseLocation.Substring(0, baseLocation.Length - 1); } } resultPath = resultPath + targetLocation.Substring(baseLocation.Length); // preprocess .\ case return resultPath.Substring(2, resultPath.Length - 3); } /// <summary> /// Resolves the relative pathes /// </summary> /// <param name="relativePath">Relative path</param> /// <param name="basePath">base path for discovering</param> /// <returns>Resolved path</returns> public static string ResolveRelativePath(string relativePath, string basePath) { if (string.IsNullOrEmpty(basePath)) { throw new ArgumentNullException("basePath"); } if (string.IsNullOrEmpty(relativePath)) { throw new ArgumentNullException("relativePath"); } var result = basePath; if (Path.IsPathRooted(relativePath)) { return relativePath; } if (relativePath.EndsWith(@"\")) { relativePath = relativePath.Substring(0, relativePath.Length - 1); } if (relativePath == ".") { return basePath; } if (relativePath.StartsWith(@".\")) { relativePath = relativePath.Substring(2); } relativePath = relativePath.Replace(@"\.\", @"\"); if (!relativePath.EndsWith(@"\")) { relativePath = relativePath + @"\"; } while (!string.IsNullOrEmpty(relativePath)) { int lengthOfOperation = relativePath.IndexOf(@"\") + 1; var operation = relativePath.Substring(0, lengthOfOperation - 1); relativePath = relativePath.Remove(0, lengthOfOperation); if (operation == @"..") { result = Path.GetDirectoryName(result); } else { result = Path.Combine(result, operation); } } return result; } } }
我们可以尝试使用Environment.CurrentDirectory将当前目录更改为包含可执行文件的目录,然后再从相对路径读取。或者,如果我们有相对路径(Path.IsPathRooted),则可以将根目录与相对路径结合在一起(Path.Combine)以使用绝对路径。