Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
Markdown Monster - The Markdown Editor for Windows

Finding a Relative Path in .NET


:P
On this page:

Here’s a nice and simple path utility that I’ve needed in a number of applications: I need to find a relative path based on a base path. So if I’m working in a folder called c:\temp\templates\ and I want to find a relative path for c:\temp\templates\subdir\test.txt I want to receive back subdir\test.txt. Or if I pass c:\ I want to get back ..\..\ – in other words always return a non-hardcoded path based on some other known directory.

I’ve had a routine in my library that does this via some lengthy string parsing routines, but ran into some Uri processing today that made me realize that this code could be greatly simplified by using the System.Uri class instead. Here’s the simple static method:

/// <summary>
/// Returns a relative path string from a full path based on a base path
/// provided.
/// </summary>
/// <param name="fullPath">The path to convert. Can be either a file or a directory</param>
/// <param name="basePath">The base path on which relative processing is based. Should be a directory.</param>
/// <returns>
/// String of the relative path.
/// 
/// Examples of returned values:
///  test.txt, ..\test.txt, ..\..\..\test.txt, ., .., subdir\test.txt
/// </returns>
public static string GetRelativePath(string fullPath, string basePath ) 
{
    // Require trailing backslash for path
    if (!basePath.EndsWith("\\"))
        basePath += "\\";

    Uri baseUri = new Uri(basePath);
    Uri fullUri = new Uri(fullPath);

    Uri relativeUri = baseUri.MakeRelativeUri(fullUri);

    // Uri's use forward slashes so convert back to backward slashes
    return relativeUri.ToString().Replace("/", "\\");

}

You can then call it like this:

string relPath = FileUtils.GetRelativePath("c:\temp\templates\subdir\test.txt","c:\temp\templates")

It’s not exactly rocket science but it’s useful in many scenarios where you’re working with files based on an application base directory. I often forget that the URI class can basically work of file paths as well to slice and dice the path portions which is a good thing to remember at times. The only thing to remember if you do use it that it turns file system backwards slashes into forward slashes so that has to be reversed out.

I needed this because right now I’m working on a templating solution (using the Razor Engine) where templates live in a base directory and are supplied as relative paths to that base directory. Resolving these relative paths both ways is important in order to properly check for existance of files and their change status in this case.

Not the kind of thing you use every day, but useful to remember.

Posted in .NET  CSharp  

The Voices of Reason


 

Kevin Dente
December 20, 2010

# re: Finding a Relative Path in .NET

Nice one. I've used P/Invoke to PathRelativePathTo before, but that requires full trust.

Patrik P
December 20, 2010

# re: Finding a Relative Path in .NET

Just a little thing.

the last line of code string relPath = FileUtils.GetRelativePath("c:\temp\templates","c:\temp\templates\subdir\test.txt")

switched the parameters.

Rick Strahl
December 21, 2010

# re: Finding a Relative Path in .NET

@Patrik - Ooops. Thanks fixed.

Rick Strahl
December 21, 2010

# re: Finding a Relative Path in .NET

@Kevin - yeah I've actually used PathRelativePath() too in non-.NET apps, but ran into trouble with the P/Invoke part. Previously I had some nasty path comparison code that would look at the full path and effectively strip out the relative path with a replace :-). It worked for what I needed but this is much cleaner and works with stepping up the hierarchy which my old code didn't do...

Simpler is better especially in this case...

Ben Hadad
September 09, 2011

# re: Finding a Relative Path in .NET

Thanks for the pointer, Rick; I knew there had to be something like that in the .NET library. Looking further, if you'd like the slashes "backslashified", it looks as though URI has that very thing in the "LocalPath" property.

Rob
February 22, 2012

# re: Finding a Relative Path in .NET

It appears to me that if your filename contains a space, the space is converted to %20, which caused a problem in my app.

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024