GetRelativePath (C#)

c# #

Determines the relative path of a file name to a reference directory.

Wenn der Pfad zu einer Datei abgespeichert werden soll, kann man ihn relativ zu einem definierten Ursprung (z. B. einer Projektdatei, die auf die andere Datei zeigt) oder absolut im gesamten Dateisystem angeben. Je nach Anwendung kann das eine oder das andere praktischer sein. Den absoluten Pfad zu speichern ist kein Kunstwerk, den hat man ja sowieso beim Auswählen oder Öffnen der Datei. Aber den kürzesten relativen Pfad von einer Datei zur anderen zu finden, das erfordert schon mehr Aufwand. Diese Arbeit nimmt die hier vorgestellte GetRelativePath-Funktion ab.

Relative Pfade in C++? Weiter zur C++-Version dieser Funktion…

Download

GetRelativePath.cs2.6 KiBQuelltext der GetRelativePath-Funktion

Contents of the file GetRelativePath.cs:

// Copyright (c) 2014, Yves Goergen, http://unclassified.software/source/getrelativepath
//
// Copying and distribution of this file, with or without modification, are permitted provided the
// copyright notice and this notice are preserved. This file is offered as-is, without any warranty.

using System;
using System.IO;

namespace Unclassified.Util
{
    public class PathUtil
    {
        /// <summary>
        /// Determines the relative path of the specified path relative to a base path.
        /// </summary>
        /// <param name="path">The path to make relative.</param>
        /// <param name="relBase">The base path.</param>
        /// <param name="throwOnDifferentRoot">If true, an exception is thrown for different roots, otherwise the source path is returned unchanged.</param>
        /// <returns>The relative path.</returns>
        public static string GetRelativePath(string path, string relBase, bool throwOnDifferentRoot = true)
        {
            // Use case-insensitive comparing of path names.
            // NOTE: This may be different on other systems.
            StringComparison sc = StringComparison.InvariantCultureIgnoreCase;

            // Are both paths rooted?
            if (!Path.IsPathRooted(path))
                throw new ArgumentException("path argument is not a rooted path.");
            if (!Path.IsPathRooted(relBase))
                throw new ArgumentException("relBase argument is not a rooted path.");

            // Do both paths share the same root?
            string pathRoot = Path.GetPathRoot(path);
            string baseRoot = Path.GetPathRoot(relBase);
            if (!string.Equals(pathRoot, baseRoot, sc))
            {
                if (throwOnDifferentRoot)
                {
                    throw new InvalidOperationException("Both paths do not share the same root.");
                }
                else
                {
                    return path;
                }
            }

            // Cut off the path roots
            path = path.Substring(pathRoot.Length);
            relBase = relBase.Substring(baseRoot.Length);

            // Cut off the common path parts
            string[] pathParts = path.Split(Path.DirectorySeparatorChar);
            string[] baseParts = relBase.Split(Path.DirectorySeparatorChar);
            int commonCount;
            for (
                commonCount = 0;
                commonCount < pathParts.Length &&
                commonCount < baseParts.Length &&
                string.Equals(pathParts[commonCount], baseParts[commonCount], sc);
                commonCount++)
            {
            }

            // Add .. for the way up from relBase
            string newPath = "";
            for (int i = commonCount; i < baseParts.Length; i++)
            {
                newPath += ".." + Path.DirectorySeparatorChar;
            }

            // Append the remaining part of the path
            for (int i = commonCount; i < pathParts.Length; i++)
            {
                newPath = Path.Combine(newPath, pathParts[i]);
            }

            return newPath;
        }
    }
}

Licence and terms of use

Copying and distribution of this file, with or without modification, are permitted provided the copyright notice and this notice are preserved. This file is offered as-is, without any warranty. (GNU All-Permissive licence)

Statistic data

  • Created on 2011-12-23, updated on 2014-09-07.