A free library to handle common and complex path operations

I just release the library NDepend.Helpers.FilePathDirectory on CodePlex. 

NDepend.Helpers.FilePathDirectory is the library used by the tool NDepend to handle common path operations. Benefits of the NDepend.Helpers.FilePathDirectory over the .NET Framework class System.IO.Path include:

  • Strongly typed File/Directory path.
  • Relative / absolute path conversion.
  • Path normalization API
  • Path validity check API
  • Path comparison API
  • Path browsing API.
  • Path rebasing API
  • List of path operations (TryGetCommonRootDirectory, GetListOfUniqueDirsAndUniqueFileNames, list equality…)

NDepend.Helpers.FilePathDirectory is 100% unit-tested and tests code is provided with the source code.

Here is a simple class diagram of the object model:

 

 

Here is some code that shows common NDepend.Helpers.FilePathDirectory use cases:

using NDepend.Helpers.FileDirectoryPath;

using System.Diagnostics;

using System.Collections.Generic;

 

class Program {

   static void Main(string[] args) {

      FilePathAbsolute filePathAbsolute1,
filePathAbsolute2;

      FilePathRelative filePathRelative1;

      DirectoryPathAbsolute directoryPathAbsolute1;

      DirectoryPathRelative directoryPathRelative1;

 

 

      //

      //  Path
normalization

      //

      filePathAbsolute1
= new FilePathAbsolute(@”C:/Dir1\\File.txt”);

      Debug.Assert(filePathAbsolute1.Path == @”C:\Dir1\File.txt”);

 

     
directoryPathAbsolute1 = new DirectoryPathAbsolute(@”C:/Dir1\\Dir2\”);

      Debug.Assert(directoryPathAbsolute1.Path == @”C:\Dir1\Dir2″);

 

     
directoryPathAbsolute1 = new DirectoryPathAbsolute(@”C:\Dir1\..\Dir2\.”);

      Debug.Assert(directoryPathAbsolute1.Path == @”C:\Dir2″);

 

 

      //

      // Path comparison

      //

      filePathAbsolute1
= new FilePathAbsolute(@”C:/Dir1\\File.txt”);

      filePathAbsolute2
= new FilePathAbsolute(@”C:\DIR1\FILE.TXT”);

      Debug.Assert(filePathAbsolute1.Equals(filePathAbsolute2));

      Debug.Assert(filePathAbsolute1 ==
filePathAbsolute2);

 

 

      //

      // Relative -> Absolute path conversion

      //

      filePathRelative1
= new FilePathRelative(@”..\..\Dir1\File.txt”);

     
directoryPathAbsolute1 = new DirectoryPathAbsolute(@”C:\Dir2\Dir3\Dir4″);

      filePathAbsolute1
= filePathRelative1.GetAbsolutePathFrom(directoryPathAbsolute1);

      Debug.Assert( filePathAbsolute1.Path == @”C:\Dir2\Dir1\File.txt”);

 

 

      //

      // Absolute -> Relative path conversion

      //

      filePathAbsolute1
= new FilePathAbsolute(@”C:\Dir1\File.txt”);

     
directoryPathAbsolute1 = new DirectoryPathAbsolute(@”C:\Dir2\Dir3\Dir4″);

      filePathRelative1
= filePathAbsolute1.GetPathRelativeFrom(directoryPathAbsolute1);

      Debug.Assert(filePathRelative1.Path == @”..\..\..\Dir1\File.txt”);

 

 

      //

      // Path string validation

      //

      string reason;

      Debug.Assert(PathHelper.IsValidAbsolutePath(@”C:\Dir2\Dir1″, out reason));

      Debug.Assert(!PathHelper.IsValidAbsolutePath(@”C:\..\Dir1″, out
reason));

      Debug.Assert(!PathHelper.IsValidAbsolutePath(@”.\Dir1″, out
reason));

      Debug.Assert(!PathHelper.IsValidAbsolutePath(@”1:\Dir1″, out
reason));

      Debug.Assert(PathHelper.IsValidRelativePath(@”.\Dir1\Dir2″, out
reason));

      Debug.Assert(PathHelper.IsValidRelativePath(@”..\Dir1\Dir2″, out reason));

      Debug.Assert(PathHelper.IsValidRelativePath(@”.\Dir1\..\Dir2″, out reason));

      Debug.Assert(!PathHelper.IsValidRelativePath(@”.\Dir1\..\..\Dir2″, out reason));

      Debug.Assert(!PathHelper.IsValidRelativePath(@”C:\Dir1\Dir2″, out reason));

 

 

      //

      // File name & extension

      //

      filePathAbsolute1
= new FilePathAbsolute(@”C:\Dir1\File.cs.Txt”);

      Debug.Assert(filePathAbsolute1.FileName == “File.cs.Txt”);

      Debug.Assert(filePathAbsolute1.FileNameWithoutExtension
== “File.cs”);

      Debug.Assert(filePathAbsolute1.FileExtension == “.Txt”);

      Debug.Assert(filePathAbsolute1.HasExtension(“.txt”));

 

 

      //

      // Path browsing

      //

      filePathAbsolute1
= new FilePathAbsolute(@”C:\Dir1\File.cs.Txt”);

      Debug.Assert(filePathAbsolute1.ParentDirectoryPath.Path
== @”C:\Dir1″);

      Debug.Assert(filePathAbsolute1.GetBrotherFileWithName(“File.xml”).Path == @”C:\Dir1\File.xml”);

      Debug.Assert(filePathAbsolute1.ParentDirectoryPath.GetChildDirectoryWithName(“Dir2″).Path == @”C:\Dir1\Dir2″);

      Debug.Assert(filePathAbsolute1.ParentDirectoryPath.GetChildDirectoryWithName(“..”).Path == @”C:”);

 

     
directoryPathRelative1 = new DirectoryPathRelative(@”..\Dir1\Dir2″);

      Debug.Assert(directoryPathRelative1.ParentDirectoryPath.Path
== @”..\Dir1″);

 

 

      //

      // Path rebasing

      //

     
directoryPathAbsolute1 = new DirectoryPathAbsolute(@”C:\Dir1\Dir2\Dir3″);

      DirectoryPathAbsolute directoryPathAbsolute2 = new DirectoryPathAbsolute(@”E:\Dir4\Dir1″);

      DirectoryPathAbsolute rebasedPath;

      PathHelper.TryRebasePath(directoryPathAbsolute1,
directoryPathAbsolute2, out rebasedPath);

      Debug.Assert(rebasedPath.Path == @”E:\Dir4\Dir1\Dir2\Dir3″);

 

 

      //

      // List of path 
ListOfPathsEquals \ Contains \ TryGetCommonRootDirectory

      //

      List<DirectoryPathAbsolute>
list1 = new List<DirectoryPathAbsolute>();

      List<DirectoryPathAbsolute>
list2 = new List<DirectoryPathAbsolute>();

      list1.Add(new DirectoryPathAbsolute(@”C:\Dir1\Dir2″));

      list2.Add(new DirectoryPathAbsolute(@”c:\dir1\dir2″));

      list1.Add(new DirectoryPathAbsolute(@”C:\Dir1\Dir3\Dir4″));

      list2.Add(new DirectoryPathAbsolute(@”c:\dir1\dir3\dir4″));

      Debug.Assert(ListOfPathHelper.ListOfPathsEquals(list1,
list2));

      Debug.Assert(ListOfPathHelper.Contains(list1,
new DirectoryPathAbsolute(@”C:\Dir1\dir2″)));

      ListOfPathHelper.TryGetCommonRootDirectory(list1, out directoryPathAbsolute1);

      Debug.Assert(directoryPathAbsolute1.Path == @”C:\Dir1″);

 

      //

      // List of path  
GetListOfUniqueDirsAndUniqueFileNames

      //

      List<FilePathAbsolute>
list = new List<FilePathAbsolute>();

      list.Add(new FilePathAbsolute(@”E:\Dir1\Dir2\File1.txt”));

      list.Add(new FilePathAbsolute(@”E:\dir1\dir2\File2.txt”));

      list.Add(new FilePathAbsolute(@”E:\Dir1\Dir2\Dir3\file2.txt”));

      List<DirectoryPathAbsolute>
listOfUniqueDirs;

      List<string>
listOfUniqueFileNames;

      ListOfPathHelper.GetListOfUniqueDirsAndUniqueFileNames(list,
out listOfUniqueDirs, out
listOfUniqueFileNames);

      Debug.Assert(listOfUniqueDirs.Count == 2);

      Debug.Assert(listOfUniqueDirs[0].Path == @”E:\Dir1\Dir2″);

      Debug.Assert(listOfUniqueDirs[1].Path == @”E:\Dir1\Dir2\Dir3″);

      Debug.Assert(listOfUniqueFileNames.Count == 2);

      Debug.Assert(listOfUniqueFileNames[0] == “File1.txt”);

      Debug.Assert(listOfUniqueFileNames[1] == “File2.txt”);

 

 

      //

      // Interaction with System.IO API

      //

      filePathAbsolute1
= new FilePathAbsolute(

        
System.Reflection.Assembly.GetExecutingAssembly().Location);

      Debug.Assert(filePathAbsolute1.Exists);

      System.IO.FileInfo fileInfo = filePathAbsolute1.FileInfo;

 

     
directoryPathAbsolute1 = filePathAbsolute1.ParentDirectoryPath as DirectoryPathAbsolute;

      Debug.Assert(directoryPathAbsolute1.Exists);

      System.IO.DirectoryInfo directoryInfo =
directoryPathAbsolute1.DirectoryInfo;

 

      List<DirectoryPathAbsolute>
listSubDir = directoryPathAbsolute1.ChildrenDirectoriesPath;

      List<FilePathAbsolute> listSubFile =
directoryPathAbsolute1.ChildrenFilesPath;

 

   }

}

This entry was posted in Featured. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://www.NDepend.com Patrick Smacchia

    “/” is not considered as a valid relative path, “.” or “./” or “.\” is.

    you can test like this:

    string reason;
    bool b = PathHelper.IsValidRelativePath(“/”, out reason);
    and b will be false

    bool b = PathHelper.IsValidAbsolutePath(“/”, out reason);
    also returns false btw

  • http://blog.dotnetwiki.org Jonathan de Halleux

    Have you tried ‘new FilePathRelative(“/”)’ ? :)

  • bwets

    Awesome, makes you wonder how MS could have missed that! I had to write my own MakeRelative method, and it was such a pain… Thanks!