and*_*ree 27 .net c# directory
我有2个字符串--dir1和dir2,我需要检查一个是否是其他的子目录.我尝试使用Contains方法:
dir1.contains(dir2);
Run Code Online (Sandbox Code Playgroud)
但是如果目录具有相似的名称,例如 - c:\abc
并且c:\abc1
不是子目录,则返回true也返回true.肯定有更好的办法.
Bro*_*ass 28
DirectoryInfo di1 = new DirectoryInfo(dir1);
DirectoryInfo di2 = new DirectoryInfo(dir2);
bool isParent = di2.Parent.FullName == di1.FullName;
Run Code Online (Sandbox Code Playgroud)
或者在循环中允许嵌套的子目录,即C:\ foo\bar\baz是C:\ foo的子目录:
DirectoryInfo di1 = new DirectoryInfo(dir1);
DirectoryInfo di2 = new DirectoryInfo(dir2);
bool isParent = false;
while (di2.Parent != null)
{
if (di2.Parent.FullName == di1.FullName)
{
isParent = true;
break;
}
else di2 = di2.Parent;
}
Run Code Online (Sandbox Code Playgroud)
ang*_*sen 24
\
和/
文件夹分隔符..\
路径c:\foobar
不是子路径c:\foo
)注意:这仅匹配路径字符串,不适用于文件系统中的符号链接和其他类型的链接.
码:
public static class StringExtensions
{
/// <summary>
/// Returns true if <paramref name="path"/> starts with the path <paramref name="baseDirPath"/>.
/// The comparison is case-insensitive, handles / and \ slashes as folder separators and
/// only matches if the base dir folder name is matched exactly ("c:\foobar\file.txt" is not a sub path of "c:\foo").
/// </summary>
public static bool IsSubPathOf(this string path, string baseDirPath)
{
string normalizedPath = Path.GetFullPath(path.Replace('/', '\\')
.WithEnding("\\"));
string normalizedBaseDirPath = Path.GetFullPath(baseDirPath.Replace('/', '\\')
.WithEnding("\\"));
return normalizedPath.StartsWith(normalizedBaseDirPath, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// Returns <paramref name="str"/> with the minimal concatenation of <paramref name="ending"/> (starting from end) that
/// results in satisfying .EndsWith(ending).
/// </summary>
/// <example>"hel".WithEnding("llo") returns "hello", which is the result of "hel" + "lo".</example>
public static string WithEnding([CanBeNull] this string str, string ending)
{
if (str == null)
return ending;
string result = str;
// Right() is 1-indexed, so include these cases
// * Append no characters
// * Append up to N characters, where N is ending length
for (int i = 0; i <= ending.Length; i++)
{
string tmp = result + ending.Right(i);
if (tmp.EndsWith(ending))
return tmp;
}
return result;
}
/// <summary>Gets the rightmost <paramref name="length" /> characters from a string.</summary>
/// <param name="value">The string to retrieve the substring from.</param>
/// <param name="length">The number of characters to retrieve.</param>
/// <returns>The substring.</returns>
public static string Right([NotNull] this string value, int length)
{
if (value == null)
{
throw new ArgumentNullException("value");
}
if (length < 0)
{
throw new ArgumentOutOfRangeException("length", length, "Length is less than zero");
}
return (length < value.Length) ? value.Substring(value.Length - length) : value;
}
}
Run Code Online (Sandbox Code Playgroud)
测试用例(NUnit):
[TestFixture]
public class StringExtensionsTest
{
[TestCase(@"c:\foo", @"c:", Result = true)]
[TestCase(@"c:\foo", @"c:\", Result = true)]
[TestCase(@"c:\foo", @"c:\foo", Result = true)]
[TestCase(@"c:\foo", @"c:\foo\", Result = true)]
[TestCase(@"c:\foo\", @"c:\foo", Result = true)]
[TestCase(@"c:\foo\bar\", @"c:\foo\", Result = true)]
[TestCase(@"c:\foo\bar", @"c:\foo\", Result = true)]
[TestCase(@"c:\foo\a.txt", @"c:\foo", Result = true)]
[TestCase(@"c:\FOO\a.txt", @"c:\foo", Result = true)]
[TestCase(@"c:/foo/a.txt", @"c:\foo", Result = true)]
[TestCase(@"c:\foobar", @"c:\foo", Result = false)]
[TestCase(@"c:\foobar\a.txt", @"c:\foo", Result = false)]
[TestCase(@"c:\foobar\a.txt", @"c:\foo\", Result = false)]
[TestCase(@"c:\foo\a.txt", @"c:\foobar", Result = false)]
[TestCase(@"c:\foo\a.txt", @"c:\foobar\", Result = false)]
[TestCase(@"c:\foo\..\bar\baz", @"c:\foo", Result = false)]
[TestCase(@"c:\foo\..\bar\baz", @"c:\bar", Result = true)]
[TestCase(@"c:\foo\..\bar\baz", @"c:\barr", Result = false)]
public bool IsSubPathOfTest(string path, string baseDirPath)
{
return path.IsSubPathOf(baseDirPath);
}
}
Run Code Online (Sandbox Code Playgroud)
更新
..\
路径,添加缺失的代码从 netstandard2.1 开始,终于有了一种几乎方便且与平台无关的方法来检查这一点:Path.GetRelativePath()。
var relPath = Path.GetRelativePath(
basePath.Replace('\\', '/'),
subPath.Replace('\\', '/'));
var isSubPath =
rel != "." && rel != ".."
&& !rel.StartsWith("../")
&& !Path.IsPathRooted(rel);
Run Code Online (Sandbox Code Playgroud)
和subPath
都basePath
必须是绝对路径。
便捷扩展功能:
public static bool IsSubPathOf(this string subPath, string basePath) {
var rel = Path.GetRelativePath(
basePath.Replace('\\', '/'),
subPath.Replace('\\', '/'));
return rel != "."
&& rel != ".."
&& !rel.StartsWith("../")
&& !Path.IsPathRooted(rel);
}
Run Code Online (Sandbox Code Playgroud)
.NET 摆弄一些测试用例:https://dotnetfiddle.net/di4ze6