Wednesday 14 May 2008

FileInfo FullName returns case insensitive results

I had a problem the other day whereby I was trying to record urls that contained encoded information as a querystring parameter, e.g. file.asp?param=4H4tTy7u

The problem was that even though I could see the files in case sensitive manner, when I saved the file to the filesystem, they were being read as case insensitive, e.g. file.asp?param=4h4tty7u

This caused major problems, as when I then unencoded the information in the querystring, I was getting completely the wrong information.

Upon tracing, it became apparent that although I could see the mixed cases in windows explorer, the underlying filesystem was case insensitive, and returned all results in lowercase - something which was causing the major problem.

To get round this, I first found an MS article that said it was caused by a .NET 2 framework bug from 2006 that set a registry value to indicate case insensitivity to the filesystem. After I changed this value and restarted, still it did not work.

After a bit of googling, I found the following article, which proved to solve the problem for me eventually - quite why such an elaborate solution is required is beyond me, but hey! of you have the same problem, at least here is the solution!


//within your code....
string sFileToProcess = fi.FullName;

string dir = Path.GetDirectoryName(sFileToProcess);
dir = ReplaceDirsWithExactCase(
dir,
Path.GetPathRoot(dir).ToUpper());
string filename =
Path.GetFileName(GetExactCaseForFilename(sFileToProcess));
Console.WriteLine(dir + "\\" + filename);



//methods needed for the above to work.
public static string ReplaceDirsWithExactCase(string fullpath, string parent)
{
if (fullpath.LastIndexOf(@"\") != fullpath.Length - 1)
fullpath += @"\";
if (parent.LastIndexOf(@"\") != parent.Length - 1)
parent += @"\";
string lookfor =
fullpath.ToLower().Replace(parent.ToLower(), "");
lookfor =
(parent + lookfor.Substring(0,
lookfor.IndexOf(@"\"))).ToLower();
string[] dirs =
Directory.GetDirectories(parent);
foreach (string dir in dirs)
if (dir.ToLower() == lookfor)
{
if (lookfor + @"\" == fullpath.ToLower())
return dir;
else
return ReplaceDirsWithExactCase(fullpath, dir);
}
return null;
}


public static string GetExactCaseForFilename(string file)
{
string[] files =
Directory.GetFiles(Path.GetDirectoryName(file));
foreach (string f in files)
if (f.ToLower() == file.ToLower())
return f;
return null;
}