Create a Relative path code snippet

Posted Wednesday, February 08, 2006 1:38 AM by pwelter34

Here is a code snippet that is equivalent to the windows API PathRelativePathTo as native c#. The function creates a relative path from one file or folder to another.

public class PathUtil

{

    /// <summary>

    /// Creates a relative path from one file

    /// or folder to another.

    /// </summary>

    /// <param name="fromDirectory">

    /// Contains the directory that defines the

    /// start of the relative path.

    /// </param>

    /// <param name="toPath">

    /// Contains the path that defines the

    /// endpoint of the relative path.

    /// </param>

    /// <returns>

    /// The relative path from the start

    /// directory to the end path.

    /// </returns>

    /// <exception cref="ArgumentNullException"></exception>

    public static string RelativePathTo(

        string fromDirectory, string toPath)

    {

        if (fromDirectory == null)

            throw new ArgumentNullException("fromDirectory");

 

        if (toPath == null)

            throw new ArgumentNullException("toPath");

 

        bool isRooted = Path.IsPathRooted(fromDirectory)

            && Path.IsPathRooted(toPath);

 

        if (isRooted)

        {

            bool isDifferentRoot = string.Compare(

                Path.GetPathRoot(fromDirectory),

                Path.GetPathRoot(toPath), true) != 0;

 

            if (isDifferentRoot)

                return toPath;                         

        }               

 

        StringCollection relativePath = new StringCollection();

        string[] fromDirectories = fromDirectory.Split(

            Path.DirectorySeparatorChar);

 

        string[] toDirectories = toPath.Split(

            Path.DirectorySeparatorChar);

 

        int length = Math.Min(

            fromDirectories.Length,

            toDirectories.Length);

 

        int lastCommonRoot = -1;

 

        // find common root

        for (int x = 0; x < length; x++)

        {

            if (string.Compare(fromDirectories[x],

                toDirectories[x], true) != 0)

                break;

 

            lastCommonRoot = x;

        }

        if (lastCommonRoot == -1)

            return toPath;

 

        // add relative folders in from path

        for (int x = lastCommonRoot + 1; x < fromDirectories.Length; x++)

            if (fromDirectories[x].Length > 0)

                relativePath.Add("..");

 

        // add to folders to path

        for (int x = lastCommonRoot + 1; x < toDirectories.Length; x++)

            relativePath.Add(toDirectories[x]);

 

        // create relative path

        string[] relativeParts = new string[relativePath.Count];

        relativePath.CopyTo(relativeParts, 0);

 

        string newPath = string.Join(

            Path.DirectorySeparatorChar.ToString(),

            relativeParts);

 

        return newPath;

    }

 

}

Filed under:

Comments

# XIU&#8217;s Blog &raquo; Blog Archive &raquo; links for 2006-06-14

Tuesday, June 13, 2006 8:27 PM by XIU’s Blog » Blog Archive » links for 2006-06-14

# re: Create a Relative path code snippet

Sunday, August 27, 2006 11:04 AM by pat

um.. where?

# re: Create a Relative path code snippet

Tuesday, October 30, 2007 10:21 PM by goole

at first i didn't see it either. but using the google cache it shows up.

72.14.253.104/search

using System;

using System.Collections.Specialized;

using System.IO;

using System.Text;

public class Path

{

/// <summary>

/// Creates a relative path from one file or folder to another.

/// </summary>

/// <param name="fromDirectory">Contains the directory that defines the start of the relative path.</param>

/// <param name="toPath">Contains the path that defines the endpoint of the relative path.</param>

/// <returns>The relative path from the start directory to the end path.</returns>

/// <exception cref="ArgumentNullException"></exception>

/// <exception cref="ArgumentException"></exception>

public static string RelativePathTo(string fromDirectory, string toPath)

{

if (fromDirectory == null)

throw new ArgumentNullException("fromDirectory");

if (toPath == null)

throw new ArgumentNullException("fromDirectory");

if (System.IO.Path.IsPathRooted(fromDirectory) && System.IO.Path.IsPathRooted(toPath))

{

if (string.Compare(System.IO.Path.GetPathRoot(fromDirectory),

System.IO.Path.GetPathRoot(toPath), true) != 0)

{

throw new ArgumentException(

string.Format("The paths '{0} and '{1}' have different path roots.",

fromDirectory, toPath));

}

}

StringCollection relativePath = new StringCollection();

string[] fromDirectories = fromDirectory.Split(System.IO.Path.DirectorySeparatorChar);

string[] toDirectories = toPath.Split(System.IO.Path.DirectorySeparatorChar);

int length = Math.Min(fromDirectories.Length, toDirectories.Length);

int lastCommonRoot = -1;

// find common root

for (int x = 0; x < length; x++)

{

if (string.Compare(fromDirectories[x], toDirectories[x], true) != 0)

break;

lastCommonRoot = x;

}

if (lastCommonRoot == -1)

{

throw new ArgumentException(

string.Format("The paths '{0} and '{1}' do not have a common prefix path.",

fromDirectory, toPath));

}

// add relative folders in from path

for (int x = lastCommonRoot + 1; x < fromDirectories.Length; x++)

if (fromDirectories[x].Length > 0)

relativePath.Add("..");

// add to folders to path

for (int x = lastCommonRoot + 1; x < toDirectories.Length; x++)

relativePath.Add(toDirectories[x]);

// create relative path

string[] relativeParts = new string[relativePath.Count];

relativePath.CopyTo(relativeParts, 0);

string newPath = string.Join(System.IO.Path.DirectorySeparatorChar.ToString(), relativeParts);

return newPath;

}

}

# re: Create a Relative path code snippet

Friday, December 21, 2007 10:09 AM by Rob Ashton

Thankyou, that saves some time!

# re: Create a Relative path code snippet

Tuesday, January 01, 2008 9:34 AM by flipdoubt

I contend Path.IsRootedPath returns false positives. For example, it returns true for "\Data". It should return false, shouldn't it? I prefer the following:

public bool MyIsRootedPath( string path )

{ return ( System.IO.Path.GetFullPath( path ) == path ); }

# re: Create a Relative path code snippet

Thursday, January 10, 2008 8:00 PM by Xaroth

Re: flipdoubt:

\Data does not specify it's a folder, it can also be a file called "Data" .. you should add a \ behind all folder names to make it clear that it is indeed a folder, and not a file.

# re: Create a Relative path code snippet

Friday, February 22, 2008 12:07 AM by John Hatton

Thanks for this, Paul. Just what I needed.

Leave a Comment

(required) 
(required) 
(optional)
(required)