j'aimais Yona's answer, mais je le voulais à:
- support chemins UNC
- Dites-moi si le chemin n'existait pas
- Utilisez l'itération au lieu de la récursivité (car elle n'utilise que la récursion de queue)
- Réduire le nombre d'appels à Path.Combine (pour réduire les concaténations de chaîne).
/// <summary>
/// Gets the exact case used on the file system for an existing file or directory.
/// </summary>
/// <param name="path">A relative or absolute path.</param>
/// <param name="exactPath">The full path using the correct case if the path exists. Otherwise, null.</param>
/// <returns>True if the exact path was found. False otherwise.</returns>
/// <remarks>
/// This supports drive-lettered paths and UNC paths, but a UNC root
/// will be returned in title case (e.g., \\Server\Share).
/// </remarks>
public static bool TryGetExactPath(string path, out string exactPath)
{
bool result = false;
exactPath = null;
// DirectoryInfo accepts either a file path or a directory path, and most of its properties work for either.
// However, its Exists property only works for a directory path.
DirectoryInfo directory = new DirectoryInfo(path);
if (File.Exists(path) || directory.Exists)
{
List<string> parts = new List<string>();
DirectoryInfo parentDirectory = directory.Parent;
while (parentDirectory != null)
{
FileSystemInfo entry = parentDirectory.EnumerateFileSystemInfos(directory.Name).First();
parts.Add(entry.Name);
directory = parentDirectory;
parentDirectory = directory.Parent;
}
// Handle the root part (i.e., drive letter or UNC \\server\share).
string root = directory.FullName;
if (root.Contains(':'))
{
root = root.ToUpper();
}
else
{
string[] rootParts = root.Split('\\');
root = string.Join("\\", rootParts.Select(part => CultureInfo.CurrentCulture.TextInfo.ToTitleCase(part)));
}
parts.Add(root);
parts.Reverse();
exactPath = Path.Combine(parts.ToArray());
result = true;
}
return result;
}
Pour les chemins UNC, ce cas, la racine (\\ Server \ Share) en cas de titre plutôt que le cas précis car il serait beaucoup plus de travail pour essayer de déterminer exactement du serveur distant nom de dossier et le nom de dossier exact du partage. Si vous souhaitez ajouter ce support, vous devrez utiliser des méthodes P/Invoke telles que NetServerEnum et NetShareEnum. Mais ceux-ci peuvent être lents et ne prennent pas en charge le filtrage initial uniquement sur le serveur et partagent les noms qui vous intéressent.
est ici une méthode de test unitaire pour TryGetExactPath (en utilisant Visual Studio Testing Extensions):
[TestMethod]
public void TryGetExactPathNameTest()
{
string machineName = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(Environment.MachineName.ToLower());
string[] testPaths = new[]
{
@"C:\Users\Public\desktop.ini",
@"C:\pagefile.sys",
@"C:\Windows\System32\cmd.exe",
@"C:\Users\Default\NTUSER.DAT",
@"C:\Program Files (x86)\Microsoft.NET\Primary Interop Assemblies",
@"C:\Program Files (x86)",
@"Does not exist",
@"\\Nas\Main\Setups",
@"\\Nas\Main\Setups\Microsoft\Visual Studio\VS 2015\vssdk_full.exe",
@"\\" + machineName + @"\C$\Windows\System32\ActionCenter.dll",
@"..",
};
Dictionary<string, string> expectedExactPaths = new Dictionary<string, string>()
{
{ @"..", Path.GetDirectoryName(Environment.CurrentDirectory) },
};
foreach (string testPath in testPaths)
{
string lowercasePath = testPath.ToLower();
bool expected = File.Exists(lowercasePath) || Directory.Exists(lowercasePath);
string exactPath;
bool actual = FileUtility.TryGetExactPath(lowercasePath, out exactPath);
actual.ShouldEqual(expected);
if (actual)
{
string expectedExactPath;
if (expectedExactPaths.TryGetValue(testPath, out expectedExactPath))
{
exactPath.ShouldEqual(expectedExactPath);
}
else
{
exactPath.ShouldEqual(testPath);
}
}
else
{
exactPath.ShouldBeNull();
}
}
}
NTFS est définitivement cas * sensible *. C'est l'API Windows qui est incohérente à ce sujet. –
Si vous remplacez 'return di.Name.ToUpper();' par 'return di.FullName.ToUpper();' (FullName), il fonctionnera même avec les chemins UNC. :-) – ygoe
J'ai aimé cette réponse, mais je l'ai adaptée avec une méthode TryGetExactPath qui prend en charge les chemins UNC, me dit si le chemin n'existe pas et utilise l'itération au lieu de la récursivité pour réduire les appels à Path.Combine. –