CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Patrick Smacchia [MVP C#]


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;

 

   }

}


Published Oct 18 2007, 02:55 PM by Patrick Smacchia
Filed under:

Comments

Scott Hanselman's Computer Zen said:

# October 19, 2007 3:05 AM

Jonathan de Halleux said:

Have you tried 'new FilePathRelative("/")' ? :)

# October 19, 2007 4:01 AM

Patrick Smacchia said:

"/" 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

# October 19, 2007 4:26 AM

Christopher Steen said:

Link Listing - October 18, 2007

# October 19, 2007 6:02 AM

Christopher Steen said:

How to build a Fluent Interface in C# [Via: blog@troyd.net (Troy DeMonbreun) ] SOA Security - Enterprise...

# October 19, 2007 6:04 AM

ASPInsiders said:

In my new ongoing quest to read source code to be a better developer , I now present the eighth an infinite

# October 19, 2007 6:11 AM

This Old Code said:

# October 19, 2007 9:29 AM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add

About Patrick Smacchia

Patrick Smacchia is a Visual C# MVP involved in software development for over 15 years. After graduating in mathematics and computer science, he has worked on software in a variety of fields including stock exchange, airline ticket reservation system as well as a satellite base station at Alcatel. He's currently a software consultant and trainer on .NET technologies as well as the lead developer of the tool NDepend which provides numerous metrics and caveats on any compiled .NET application. He is the author of Practical .NET2 and C#2, a .NET book conceived from real world experience with 647 compilable code listings. Check out Devlicio.us!

Our Sponsors

Free Tech Publications