如何比较C#中的(目录)路径?
如果我有两个如何比较C#中的(目录)路径?,c#,.net,path,filesystems,C#,.net,Path,Filesystems,如果我有两个DirectoryInfo对象,如何比较它们的语义平等性?例如,以下路径应全部视为等于C:\temp: C:\temp C:\temp\ C:\temp\. C:\temp\x\..\temp\. 以下各项可能等于也可能不等于C:\temp: \temp如果当前工作目录位于驱动器C:\ temp如果当前工作目录是C:\ C:\temp. C:\temp…\ 如果考虑当前的工作目录是很重要的,我可以自己解决这个问题,所以这并不重要。尾随点在windows中被剥离,所以这些路径实
DirectoryInfo
对象,如何比较它们的语义平等性?例如,以下路径应全部视为等于C:\temp
:
C:\temp
C:\temp\
C:\temp\.
C:\temp\x\..\temp\.
如果当前工作目录位于驱动器\temp
C:\
如果当前工作目录是temp
C:\
C:\temp.
C:\temp…\
bool equals = myDirectoryInfo1.FullName == myDirectoryInfo2.FullName;
?似乎p/调用将是最可靠的解决方案
UPD:Oops,我没有考虑到您不使用任何I/O的愿望,“Name”属性是相等的。采取:
DirectoryInfo dir1 = new DirectoryInfo("C:\\Scratch");
DirectoryInfo dir2 = new DirectoryInfo("C:\\Scratch\\");
DirectoryInfo dir3 = new DirectoryInfo("C:\\Scratch\\4760");
DirectoryInfo dir4 = new DirectoryInfo("C:\\Scratch\\4760\\..\\");
dir1.Name==dir2.Name和dir2.Name==dir4.Name
(本例中为“Scratch”。dir3==4760)。)只有全名属性不同
在给定两个DirectoryInfo类的情况下,您可以使用递归方法检查每个父类的名称属性,以确保完整路径相同
编辑:这适合您的情况吗?创建控制台应用程序并将其粘贴到整个Program.cs文件上。为AreEquals()函数提供两个DirectoryInfo对象,如果它们是同一个目录,则返回True。如果愿意,您可以将这个AreEquals()
方法调整为DirectoryInfo上的扩展方法,这样您就可以执行myDirectoryInfo.IsEquals(myOtherDirectoryInfo)代码>
使用系统;
使用系统诊断;
使用System.IO;
使用System.Collections.Generic;
命名空间控制台应用程序3
{
班级计划
{
静态void Main(字符串[]参数)
{
控制台写入线(AREEQUALE)(
新目录信息(“C:\\Scratch”),
新目录信息(“C:\\Scratch\\”);
控制台写入线(AREEQUALE)(
新目录信息(“C:\\Windows\\Microsoft.NET\\Framework”),
新目录信息(“C:\\Windows\\Microsoft.NET\\Framework\\v3.5\\1033\\\”);
控制台写入线(AREEQUALE)(
新目录信息(“C:\\Scratch\\”,
新目录信息(“C:\\Scratch\\4760\\\”);
Console.WriteLine(“按ENTER键继续”);
Console.ReadLine();
}
私有静态布尔值相等(DirectoryInfo dir1,DirectoryInfo dir2)
{
DirectoryInfo parent1=dir1;
DirectoryInfo parent2=dir2;
/*建立一个家长列表*/
List folder1Parents=新列表();
List folder2Parents=新列表();
while(parent1!=null)
{
folder1Parents.Add(parent1.Name);
parent1=parent1.parent1;
}
while(parent2!=null)
{
folder2Parents.Add(parent2.Name);
parent2=parent2.parent2;
}
/*现在比较一下列表*/
if(folder1Parents.Count!=folder2Parents.Count)
{
//不能相同-不同数量的家长
返回false;
}
布尔等于真;
for(int i=0;i在.NET中实现路径有一些不足之处。对此有很多抱怨,NDepend的创始人发表了一篇文章。如果您在应用程序中对路径执行大量比较操作,此库可能会对您有用。GetFullPath
似乎可以完成这项工作,但大小写差异(Path.GetFullPath(“test”)!=Path.GetFullPath(“test”)和尾部斜杠除外。
因此,以下代码应该可以正常工作:
String.Compare(
Path.GetFullPath(path1).TrimEnd('\\'),
Path.GetFullPath(path2).TrimEnd('\\'),
StringComparison.InvariantCultureIgnoreCase)
或者,如果您想以DirectoryInfo
开头:
String.Compare(
dirinfo1.FullName.TrimEnd('\\'),
dirinfo2.FullName.TrimEnd('\\'),
StringComparison.InvariantCultureIgnoreCase)
使用系统;
使用System.Collections.Generic;
使用系统文本;
命名空间EventAnalysis.IComparerImplementation
{
公共密封类FSChangeElemComparerByPath:IComparer
{
公共国际公司
String.Compare(
Path.GetFullPath(path1).TrimEnd('\\'),
Path.GetFullPath(path2).TrimEnd('\\'),
StringComparison.InvariantCultureIgnoreCase)
String.Compare(
dirinfo1.FullName.TrimEnd('\\'),
dirinfo2.FullName.TrimEnd('\\'),
StringComparison.InvariantCultureIgnoreCase)
using System;
using System.Collections.Generic;
using System.Text;
namespace EventAnalysis.IComparerImplementation
{
public sealed class FSChangeElemComparerByPath : IComparer<FSChangeElem>
{
public int Compare(FSChangeElem firstPath, FSChangeElem secondPath)
{
return firstPath.strObjectPath == null ?
(secondPath.strObjectPath == null ? 0 : -1) :
(secondPath.strObjectPath == null ? 1 : ComparerWrap(firstPath.strObjectPath, secondPath.strObjectPath));
}
private int ComparerWrap(string stringA, string stringB)
{
int length = 0;
int start = 0;
List<string> valueA = new List<string>();
List<string> valueB = new List<string>();
ListInit(ref valueA, stringA);
ListInit(ref valueB, stringB);
if (valueA.Count != valueB.Count)
{
length = (valueA.Count > valueB.Count)
? valueA.Count : valueB.Count;
if (valueA.Count != length)
{
for (int i = 0; i < length - valueA.Count; i++)
{
valueA.Add(string.Empty);
}
}
else
{
for (int i = 0; i < length - valueB.Count; i++)
{
valueB.Add(string.Empty);
}
}
}
else
length = valueA.Count;
return RecursiveComparing(valueA, valueB, length, start);
}
private void ListInit(ref List<string> stringCollection, string stringToList)
{
foreach (string s in stringToList.Remove(0, 2).Split('\\'))
{
stringCollection.Add(s);
}
}
private int RecursiveComparing(List<string> valueA, List<string> valueB, int length, int start)
{
int result = 0;
if (start != length)
{
if (valueA[start] == valueB[start])
{
result = RecursiveComparing(valueA, valueB, length, ++start);
}
else
{
result = String.Compare(valueA[start], valueB[start]);
}
}
else
return 0;
return result;
}
}
}
public static string NormalizePath(string path)
{
return Path.GetFullPath(new Uri(path).LocalPath)
.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
.ToUpperInvariant();
}
bool pathsEqual = NormalizePath(path1) == NormalizePath(path2);
bool Equals(string path1, string path2)
{
return new Uri(path1) == new Uri(path2);
}
var mm = new Minimatcher(searchPattern, new Options { AllowWindowsPaths = true });
if (mm.IsMatch(somePath))
{
// The path matches! Do some cool stuff!
}
var matchingPaths = mm.Filter(allPaths);
var mm = new Minimatcher(searchPattern, new Options { AllowWindowsPaths = true });
public static bool AreDirsEqual(string dirName1, string dirName2, bool resolveJunctionaAndNetworkPaths = true)
{
if (string.IsNullOrEmpty(dirName1) || string.IsNullOrEmpty(dirName2))
return dirName1==dirName2;
dirName1 = NormalizePath(dirName1); //assume NormalizePath normalizes/fixes case and path separators to Path.DirectorySeparatorChar
dirName2 = NormalizePath(dirName2);
int i1 = dirName1.Length;
int i2 = dirName2.Length;
do
{
--i1; --i2;
if (i1 < 0 || i2 < 0)
return i1 < 0 && i2 < 0;
} while (dirName1[i1] == dirName2[i2]);//If you want to deal with international character sets, i.e. if NormalixePath does not fix case, this comparison must be tweaked
if( !resolveJunctionaAndNetworkPaths )
return false;
for(++i1, ++i2; i1 < dirName1.Length; ++i1, ++i2)
{
if (dirName1[i1] == Path.DirectorySeparatorChar)
{
dirName1 = dirName1.Substring(0, i1);
dirName2 = dirName1.Substring(0, i2);
break;
}
}
return AreFileSystemObjectsEqual(dirName1, dirName2);
}
public static bool AreFileSystemObjectsEqual(string dirName1, string dirName2)
{
//NOTE: we cannot lift the call to GetFileHandle out of this routine, because we _must_
// have both file handles open simultaneously in order for the objectFileInfo comparison
// to be guaranteed as valid.
using (SafeFileHandle directoryHandle1 = GetFileHandle(dirName1), directoryHandle2 = GetFileHandle(dirName2))
{
BY_HANDLE_FILE_INFORMATION? objectFileInfo1 = GetFileInfo(directoryHandle1);
BY_HANDLE_FILE_INFORMATION? objectFileInfo2 = GetFileInfo(directoryHandle2);
return objectFileInfo1 != null
&& objectFileInfo2 != null
&& (objectFileInfo1.Value.FileIndexHigh == objectFileInfo2.Value.FileIndexHigh)
&& (objectFileInfo1.Value.FileIndexLow == objectFileInfo2.Value.FileIndexLow)
&& (objectFileInfo1.Value.VolumeSerialNumber == objectFileInfo2.Value.VolumeSerialNumber);
}
}
static SafeFileHandle GetFileHandle(string dirName)
{
const int FILE_ACCESS_NEITHER = 0;
//const int FILE_SHARE_READ = 1;
//const int FILE_SHARE_WRITE = 2;
//const int FILE_SHARE_DELETE = 4;
const int FILE_SHARE_ANY = 7;//FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE
const int CREATION_DISPOSITION_OPEN_EXISTING = 3;
const int FILE_FLAG_BACKUP_SEMANTICS = 0x02000000;
return CreateFile(dirName, FILE_ACCESS_NEITHER, FILE_SHARE_ANY, System.IntPtr.Zero, CREATION_DISPOSITION_OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, System.IntPtr.Zero);
}
static BY_HANDLE_FILE_INFORMATION? GetFileInfo(SafeFileHandle directoryHandle)
{
BY_HANDLE_FILE_INFORMATION objectFileInfo;
if ((directoryHandle == null) || (!GetFileInformationByHandle(directoryHandle.DangerousGetHandle(), out objectFileInfo)))
{
return null;
}
return objectFileInfo;
}
[DllImport("kernel32.dll", EntryPoint = "CreateFileW", CharSet = CharSet.Unicode, SetLastError = true)]
static extern SafeFileHandle CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode,
IntPtr SecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool GetFileInformationByHandle(IntPtr hFile, out BY_HANDLE_FILE_INFORMATION lpFileInformation);
[StructLayout(LayoutKind.Sequential)]
public struct BY_HANDLE_FILE_INFORMATION
{
public uint FileAttributes;
public System.Runtime.InteropServices.ComTypes.FILETIME CreationTime;
public System.Runtime.InteropServices.ComTypes.FILETIME LastAccessTime;
public System.Runtime.InteropServices.ComTypes.FILETIME LastWriteTime;
public uint VolumeSerialNumber;
public uint FileSizeHigh;
public uint FileSizeLow;
public uint NumberOfLinks;
public uint FileIndexHigh;
public uint FileIndexLow;
};
public bool PathEquals(string Path1, string Path2)
{
FileInfo f1 = new FileInfo(Path1.Trim('\\','/','.'));
FileInfo f2 = new FileInfo(Path2.Trim('\\', '/','.'));
if(f1.Name.ToLower() == f2.Name.ToLower())
{
return DirectoryEquals(f1.Directory, f2.Directory);
}
else
{
return false;
}
}
public bool DirectoryEquals(DirectoryInfo d1, DirectoryInfo d2)
{
if(d1.Name.ToLower() == d2.Name.ToLower())
{
if((d1.Parent != null) && (d2.Parent != null))
{
return DirectoryEquals(d1.Parent, d2.Parent);
}
else
{
return true;//C:\Temp1\Temp2 equals \Temp1\Temp2
//return (d1.Parent == null) && (d2.Parent == null);//C:\Temp1\Temp2 does not equal \Temp1\Temp2
}
}
else
{
return false;
}
}