tags:

views:

463

answers:

6

Does anyone know of any good library that abstracts the problem of path manipulation in a nice way? I'd like to be able to combine and parse paths with arbitrary separators ('/' or ':' for example) without reinventing the wheel.

It's a shame that System.IO.Path isn't more reusable.

Thanks

+1  A: 

System.IO.Path.Combine will work great for many different types of paths:

http://msdn.microsoft.com/en-us/library/system.io.path.combine.aspx

System.IO.Path.Combine uses the current platform standard separators to combine paths. That means on Windows it uses "\" and on unix/linux (mono) it uses "/". Can you give some samples of what paths you are trying to combine and on what platform?

Espo
Afraid System.IO.Path does not help because the separator characters it uses and understands are predefined. As I stated, I need to use arbitrary separator characters such as ':' and '/'. Best I can do with System.IO.Path is convert my arbitrary characters to those it recognizes (such as '\') and then convert back again after. But that is a hacky solution at best.
Kent Boogaart
A: 

Can you use Path.DirectorySeparatorChar?

Ian Oxley
A: 

You're describing regular expressions! Use that as the underpinning for what you need to do.

rp
Sure, regular expressions will work and that is what I've used up until now. But they seem like overkill and are unlikely to perform as well as a dedicated path manipulation library. Afterall, System.IO.Path doesn't use regular expression in its implementation, does it?
Kent Boogaart
+1  A: 

Check Patrick's library to handle path operations link text

This is the codeplex project

Aaron Fischer
Thanks - that library looks useful, but it still doesn't allow a custom path separator to be specified. It just uses Path.DirectorySeparatorChar.
Kent Boogaart
A: 

I can't tell what environment you might be using based off of your separators, but I have never seen a library like this before.

So using reflector and System.IO.Path as a basis it isn't difficult to reinvent the wheel.

  • Create an instance of this class
  • Supply your separator characters in the CTor
  • Optionally change the InvalidPathChars if needed.

This is pretty much the code that is used by the framework so it should be just as fast or only a negligible difference. May or may not be faster than RegEx, it is probably worth a test though.

class ArbitraryPath
{
 private readonly char _directorySeparatorChar;
 private readonly char _altDirectorySeparatorChar;
 private readonly char _volumeSeparatorChar;

 public ArbitraryPath(char directorySeparatorChar, char altDirectorySeparatorChar, char volumeSeparatorChar)
 {
  _directorySeparatorChar = directorySeparatorChar;
  _altDirectorySeparatorChar = altDirectorySeparatorChar;
  _volumeSeparatorChar = volumeSeparatorChar;
 }

 public string Combine(string path1, string path2)
 {
  if ((path1 == null) || (path2 == null))
  {
   throw new ArgumentNullException((path1 == null) ? "path1" : "path2");
  }
  CheckInvalidPathChars(path1);
  CheckInvalidPathChars(path2);
  if (path2.Length == 0)
  {
   return path1;
  }
  if (path1.Length == 0)
  {
   return path2;
  }
  if (IsPathRooted(path2))
  {
   return path2;
  }

  char ch = path1[path1.Length - 1];
  if (ch != _directorySeparatorChar && ch != _altDirectorySeparatorChar && ch != _volumeSeparatorChar)
  {
   return (path1 + _directorySeparatorChar + path2);
  }
  return (path1 + path2);
 }

 public bool IsPathRooted(string path)
 {
  if (path != null)
  {
   CheckInvalidPathChars(path);
   int length = path.Length;
   if (length >= 1 && (path[0] == _directorySeparatorChar || path[0] == _altDirectorySeparatorChar) || length >= 2 && path[1] == _volumeSeparatorChar)
   {
    return true;
   }
  }
  return false;
 }

 internal static void CheckInvalidPathChars(string path)
 {
  for (int i = 0; i < path.Length; i++)
  {
   int num2 = path[i];
   if (num2 == 0x22 || num2 == 60 || num2 == 0x3e || num2 == 0x7c || num2 < 0x20)
   {
    throw new ArgumentException("Argument_InvalidPathChars");
   }
  }
 } 

}
Bob
A: 

I'm afraid you'll have to implement a path class yourself, as I did. It gives the following advantages:

  • you can profit from type safety
  • you can override operator/, which makes concatenation easier
  • you can add convenience member functions such as GetParentPath() and GetLeafPart()
Dimitri C.