-1

I've gotten into the habit of always putting a trailing slash at the end of my folder paths and this appears to be the norm (e.g. Visual Studio macros such as $(ProjectDir) always have a trailing slash). In addition, when I'm appending a relative path to the end of an existing folder path I always put a leading slash just in case the folder path that is passed to me doesn't have a trailing slash (e.g. Windows batch: set FULL_FILE_PATH=%FOLDER_PATH%\path\to\some\file).

That being said, I tend to end up with paths that look like this C:\path\to\folder\\path\to\some\file.txt (note the two backslashes in a row). In addition, since I'm using dev\src dev\include and dev\script folder structure (where .vcxproj files and similar go in the script folder), most of my paths append a relative path with up-levels to at the end of some macro like $(ProjectDir) (e.g. Include dir = $(ProjectDir)\..\include\).

In the following code somePath02Uri and somePath03Uri return (what I believe to be) incorrect results:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DotNet45SystemUriTest
{
   class Program
   {
      static void Main(string[] args)
      {
         Console.WriteLine("We will now test the System.Uri constructor:\n");

         // Output from Console.WriteLine is in the comment on the same line

         String somePath01 = "C:\\some\\common\\..\\include\\";
         Console.WriteLine("somePath01 = " + somePath01); // somePath01 = C:\some\common\..\include\
         Uri somePath01Uri = new Uri(somePath01);
         Console.WriteLine("somePath01Uri = " + somePath01Uri.ToString()); // somePath01Uri = file:///C:/some/include/

         Console.WriteLine();

         String somePath02 = "C:\\some\\common\\\\..\\include\\";
         Console.WriteLine("somePath02 = " + somePath02); // somePath02 = C:\some\common\\..\include\
         Uri somePath02Uri = new Uri(somePath02);
         Console.WriteLine("somePath02Uri = " + somePath02Uri.ToString()); // somePath02Uri = file:///C:/some/common/include/

         Console.WriteLine();

         String somePath03 = "C:\\some\\common\\\\\\..\\include\\";
         Console.WriteLine("somePath03 = " + somePath03); // somePath03 = C:\some\common\\\..\include\
         Uri somePath03Uri = new Uri(somePath03);
         Console.WriteLine("somePath03Uri = " + somePath03Uri.ToString()); // somePath03Uri = file:///C:/some/common//include/

         Console.WriteLine();
      }
   }
}

Why does System.Uri interpret two slashes in a row as folder?

Almost forgot: If you do encounter this a quick and dirty solution is to remove the two backslashes in a row from the string before creating the Uri object. I did this by adding .Replace("\\\\", "\\"):

         String somePath02 = "C:\\some\\common\\\\..\\include\\";
         Console.WriteLine("somePath02 = " + somePath02); // somePath02 = C:\some\common\\..\include\
         Uri somePath02Uri = new Uri(somePath02.Replace("\\\\", "\\"));
         Console.WriteLine("somePath02Uri = " + somePath02Uri.ToString()); // somePath02Uri = file:///C:/some/include/
Benrobot
  • 2,630
  • 1
  • 21
  • 24
  • Its nothing to do with URI but escaping control characters in c# strings. you could also use the @ symbol for this, for example `String somePath02 = @"C:\some\common\\..\include\";` is the same as `String somePath02 = "C:\\some\\common\\\\..\\include\\";` The @ symbol tells the compiler that the following string doesn't contain control characters. – Ron Beyer Jul 17 '15 at 14:04
  • @Ron Beyer: Hi Ron, I'm not sure that you had a chance to look at the output from the Uri. If I provide a path of `C:\topLevelFolder1\..\topLevelFolder2` then I expect the resolved absolute path to be `C:\topLevelFolder2`. Likewise, if I provide a path of `C:\topLevelFolder1\\..\topLevelFolder2` I still expected the resolved absolute path to be `C:\topLevelFolder2`. – Benrobot Jul 17 '15 at 14:12
  • 1
    Have you tried specifying the UriKind as Relative? I think it defaults to absolute... As far as why, blank folder names are actually allowed by the system, so it interprets two slashes as a blank named folder. See this for how to create them: http://www.thewindowsclub.com/how-to-create-blank-folder-names-windows – Ron Beyer Jul 17 '15 at 14:16
  • Please take a look at implementing [Path.Combine()](https://msdn.microsoft.com/en-gb/library/fyy7a5kt%28v=vs.110%29.aspx) instead of concatenating our own path. This will eliminate the double \\ that you are getting. – Bernd Linde Jul 17 '15 at 14:22
  • @RonBeyer The folder name created in your link is *not* the same as having no name at all. Completely blank folder names are not supported by a windows system at all. It might not look like it, but there is an actual character that is being used as the name for that folder. – Ichabod Clay Jul 17 '15 at 14:34
  • @Ron Beyer: I have tried after your suggestion (`new Uri(somePath04, UriKind.Relative);`) and the ToString() returned `C:\some\common\\..\include\` so at least the path remains correct (in my opinion). I believe that you provided the answer when you explained that blank folder names are allowed. If you post this as the answer I'll mark it as such. – Benrobot Jul 17 '15 at 14:35
  • @Bern Linde: Path.Combine() would probably work, however, in is this case the paths I am received have already been combined by some previous system. – Benrobot Jul 17 '15 at 14:36
  • @IchabodClay, try it out, running a "dir" command on the desktop after creating that folder shows a directory without a name... – Ron Beyer Jul 17 '15 at 14:37

1 Answers1

0

The two slashes ar used for non escaping.

For example try this:

string path = "c:\test\html";

When you compile this piece of code you will get an error "Unrecognized escape sequence".

But if you add an extra slash, you tell the complier that there is no escaping intended and the string should be parsed as it is.

string path = "c:\\test\\html";

Another intresting method for non escaping is:

string path = @"c:\test\html";

Ceparu Stefan
  • 327
  • 2
  • 4
  • 13
  • I'm sorry but your question is asked in the wrong way because the Uri() doesn't interpret two slashes as folder. Like @Ron Beyer said It's has nothing to do with Uri(), it's a escaping/compiler thing. From what I've seen you want the Uri to be able to interpret a path like "C:\topLevelFolder1\\\\\\\\\...\topLevelFolder2"....in this case you should ask Microsoft to add this new feature. – Ceparu Stefan Jul 18 '15 at 16:35
  • Even Ron Beyer confirmed that "blank folder names are actually allowed by the system" which, to me, means that Uri() is, in fact, interpreting two slashes as a folder (or at least the empty string that Uri pretends to be between those two slashes is interpreted as a folder). – Benrobot Jul 19 '15 at 11:37