Лучший способ проверить, является ли Путь файлом или каталогом?
Я обрабатываю TreeView
каталогов и файлов. Пользователь может выбрать либо файл, либо каталог, а затем сделать что-то с ним. Для этого требуется, чтобы у меня был метод, который выполняет различные действия на основе выбора пользователя.
В настоящий момент я делаю что-то вроде этого, чтобы определить, является ли путь файлом или каталогом:
bool bIsFile = false;
bool bIsDirectory = false;
try
{
string[] subfolders = Directory.GetDirectories(strFilePath);
bIsDirectory = true;
bIsFile = false;
}
catch(System.IO.IOException)
{
bIsFolder = false;
bIsFile = true;
}
Я не могу не чувствовать, что есть лучший способ сделать это! Я надеялся найти стандартный метод .NET, чтобы справиться с этим, но я не смог этого сделать. Существует ли такой метод, а если нет, то какие самые простые способы определить, является ли путь файлом или каталогом?
Ответы
Ответ 1
Из Как определить, является ли путь файлом или каталогом:
// get the file attributes for file or directory
FileAttributes attr = File.GetAttributes(@"c:\Temp");
//detect whether its a directory or file
if ((attr & FileAttributes.Directory) == FileAttributes.Directory)
MessageBox.Show("Its a directory");
else
MessageBox.Show("Its a file");
Обновление для .NET 4.0 +
В комментариях ниже, если вы используете .NET 4.0 или новее (и максимальная производительность не критична), вы можете написать код более чистым способом:
// get the file attributes for file or directory
FileAttributes attr = File.GetAttributes(@"c:\Temp");
if (attr.HasFlag(FileAttributes.Directory))
MessageBox.Show("Its a directory");
else
MessageBox.Show("Its a file");
Ответ 2
Как их использовать?
File.Exists();
Directory.Exists();
Ответ 3
Только с этой строкой вы можете получить, если путь - это каталог или файл:
File.GetAttributes(data.Path).HasFlag(FileAttributes.Directory)
Ответ 4
В качестве альтернативы Directory.Exists() вы можете использовать метод File.GetAttributes() для получения атрибутов файла или каталога, чтобы вы могли создать вспомогательный метод, подобный этому:
private static bool IsDirectory(string path)
{
System.IO.FileAttributes fa = System.IO.File.GetAttributes(path);
bool isDirectory = false;
if ((fa & FileAttributes.Directory) != 0)
{
isDirectory = true;
}
return isDirectory;
}
Вы также можете рассмотреть возможность добавления объекта в свойство тега элемента управления TreeView при заполнении элемента управления, который содержит дополнительные метаданные для элемента. Например, вы можете добавить объект FileInfo для файлов и объект DirectoryInfo для каталогов, а затем проверить тип элемента в свойстве тега для сохранения дополнительных системных вызовов для получения этих данных при нажатии на элемент.
Ответ 5
Самый точный подход будет заключаться в использовании некоторого кода взаимодействия из файла shlwapi.dll
[DllImport(SHLWAPI, CharSet = CharSet.Unicode)]
[return: MarshalAsAttribute(UnmanagedType.Bool)]
[ResourceExposure(ResourceScope.None)]
internal static extern bool PathIsDirectory([MarshalAsAttribute(UnmanagedType.LPWStr), In] string pszPath);
Затем вы вызываете это следующим образом:
#region IsDirectory
/// <summary>
/// Verifies that a path is a valid directory.
/// </summary>
/// <param name="path">The path to verify.</param>
/// <returns><see langword="true"/> if the path is a valid directory;
/// otherwise, <see langword="false"/>.</returns>
/// <exception cref="T:System.ArgumentNullException">
/// <para><paramref name="path"/> is <see langword="null"/>.</para>
/// </exception>
/// <exception cref="T:System.ArgumentException">
/// <para><paramref name="path"/> is <see cref="F:System.String.Empty">String.Empty</see>.</para>
/// </exception>
public static bool IsDirectory(string path)
{
return PathIsDirectory(path);
}
Ответ 6
Это было лучшее, что я мог придумать, учитывая поведение свойств Exists и Attributes:
using System.IO;
public static class FileSystemInfoExtensions
{
/// <summary>
/// Checks whether a FileInfo or DirectoryInfo object is a directory, or intended to be a directory.
/// </summary>
/// <param name="fileSystemInfo"></param>
/// <returns></returns>
public static bool IsDirectory(this FileSystemInfo fileSystemInfo)
{
if (fileSystemInfo == null)
{
return false;
}
if ((int)fileSystemInfo.Attributes != -1)
{
// if attributes are initialized check the directory flag
return fileSystemInfo.Attributes.HasFlag(FileAttributes.Directory);
}
// If we get here the file probably doesn't exist yet. The best we can do is
// try to judge intent. Because directories can have extensions and files
// can lack them, we can't rely on filename.
//
// We can reasonably assume that if the path doesn't exist yet and
// FileSystemInfo is a DirectoryInfo, a directory is intended. FileInfo can
// make a directory, but it would be a bizarre code path.
return fileSystemInfo is DirectoryInfo;
}
}
Здесь он проверяет:
[TestMethod]
public void IsDirectoryTest()
{
// non-existing file, FileAttributes not conclusive, rely on type of FileSystemInfo
const string nonExistentFile = @"C:\TotallyFakeFile.exe";
var nonExistentFileDirectoryInfo = new DirectoryInfo(nonExistentFile);
Assert.IsTrue(nonExistentFileDirectoryInfo.IsDirectory());
var nonExistentFileFileInfo = new FileInfo(nonExistentFile);
Assert.IsFalse(nonExistentFileFileInfo.IsDirectory());
// non-existing directory, FileAttributes not conclusive, rely on type of FileSystemInfo
const string nonExistentDirectory = @"C:\FakeDirectory";
var nonExistentDirectoryInfo = new DirectoryInfo(nonExistentDirectory);
Assert.IsTrue(nonExistentDirectoryInfo.IsDirectory());
var nonExistentFileInfo = new FileInfo(nonExistentDirectory);
Assert.IsFalse(nonExistentFileInfo.IsDirectory());
// Existing, rely on FileAttributes
const string existingDirectory = @"C:\Windows";
var existingDirectoryInfo = new DirectoryInfo(existingDirectory);
Assert.IsTrue(existingDirectoryInfo.IsDirectory());
var existingDirectoryFileInfo = new FileInfo(existingDirectory);
Assert.IsTrue(existingDirectoryFileInfo.IsDirectory());
// Existing, rely on FileAttributes
const string existingFile = @"C:\Windows\notepad.exe";
var existingFileDirectoryInfo = new DirectoryInfo(existingFile);
Assert.IsFalse(existingFileDirectoryInfo.IsDirectory());
var existingFileFileInfo = new FileInfo(existingFile);
Assert.IsFalse(existingFileFileInfo.IsDirectory());
}
Ответ 7
Здесь моя:
bool IsPathDirectory(string path)
{
if (path == null) throw new ArgumentNullException("path");
path = path.Trim();
if (Directory.Exists(path))
return true;
if (File.Exists(path))
return false;
// neither file nor directory exists. guess intention
// if has trailing slash then it a directory
if (new[] {"\\", "/"}.Any(x => path.EndsWith(x)))
return true; // ends with slash
// if has extension then its a file; directory otherwise
return string.IsNullOrWhiteSpace(Path.GetExtension(path));
}
Это похоже на ответы других, но не совсем то же самое.
Ответ 8
Я столкнулся с этим, столкнувшись с подобной проблемой, за исключением того, что мне нужно было проверить, существует ли путь к файлу или папке, когда этот файл или папка могут вообще не существовать. Было несколько комментариев по вышеприведенным ответам, в которых говорилось, что они не будут работать для этого сценария. Я нашел решение (я использую VB.NET, но вы можете конвертировать, если вам нужно), который, кажется, работает хорошо для меня:
Dim path As String = "myFakeFolder\ThisDoesNotExist\"
Dim bIsFolder As Boolean = (IO.Path.GetExtension(path) = "")
'returns True
Dim path As String = "myFakeFolder\ThisDoesNotExist\File.jpg"
Dim bIsFolder As Boolean = (IO.Path.GetExtension(path) = "")
'returns False
Надеюсь, это может быть полезно кому-то!
Ответ 9
soooo в конце игры, которую я знаю, но думал, что я все равно поделюсь этим. Если вы работаете исключительно с путями в виде строк, то вычислять это легко, как пирог:
private bool IsFolder(string ThePath)
{
string BS = Path.DirectorySeparatorChar.ToString();
return Path.GetDirectoryName(ThePath) == ThePath.TrimEnd(BS.ToCharArray());
}
например:
ThePath == "C:\SomeFolder\File1.txt"
в конечном итоге будет следующим:
return "C:\SomeFolder" == "C:\SomeFolder\File1.txt" (FALSE)
Другой пример:
ThePath == "C:\SomeFolder\"
в конечном итоге будет следующим:
return "C:\SomeFolder" == "C:\SomeFolder" (TRUE)
И это также будет работать без обратной обратной косой черты:
ThePath == "C:\SomeFolder"
в конечном итоге будет следующим:
return "C:\SomeFolder" == "C:\SomeFolder" (TRUE)
Имейте в виду, что это работает только с самими путями, а не с отношением между контуром и "физическим диском"... поэтому он не может сказать вам, существует ли путь/файл или что-то в этом роде, но он обязательно скажет вам, является ли путь папкой или файлом...
Ответ 10
Здесь мы используем:
using System;
using System.IO;
namespace crmachine.CommonClasses
{
public static class CRMPath
{
public static bool IsDirectory(string path)
{
if (path == null)
{
throw new ArgumentNullException("path");
}
string reason;
if (!IsValidPathString(path, out reason))
{
throw new ArgumentException(reason);
}
if (!(Directory.Exists(path) || File.Exists(path)))
{
throw new InvalidOperationException(string.Format("Could not find a part of the path '{0}'",path));
}
return (new System.IO.FileInfo(path).Attributes & FileAttributes.Directory) == FileAttributes.Directory;
}
public static bool IsValidPathString(string pathStringToTest, out string reasonForError)
{
reasonForError = "";
if (string.IsNullOrWhiteSpace(pathStringToTest))
{
reasonForError = "Path is Null or Whitespace.";
return false;
}
if (pathStringToTest.Length > CRMConst.MAXPATH) // MAXPATH == 260
{
reasonForError = "Length of path exceeds MAXPATH.";
return false;
}
if (PathContainsInvalidCharacters(pathStringToTest))
{
reasonForError = "Path contains invalid path characters.";
return false;
}
if (pathStringToTest == ":")
{
reasonForError = "Path consists of only a volume designator.";
return false;
}
if (pathStringToTest[0] == ':')
{
reasonForError = "Path begins with a volume designator.";
return false;
}
if (pathStringToTest.Contains(":") && pathStringToTest.IndexOf(':') != 1)
{
reasonForError = "Path contains a volume designator that is not part of a drive label.";
return false;
}
return true;
}
public static bool PathContainsInvalidCharacters(string path)
{
if (path == null)
{
throw new ArgumentNullException("path");
}
bool containedInvalidCharacters = false;
for (int i = 0; i < path.Length; i++)
{
int n = path[i];
if (
(n == 0x22) || // "
(n == 0x3c) || // <
(n == 0x3e) || // >
(n == 0x7c) || // |
(n < 0x20) // the control characters
)
{
containedInvalidCharacters = true;
}
}
return containedInvalidCharacters;
}
public static bool FilenameContainsInvalidCharacters(string filename)
{
if (filename == null)
{
throw new ArgumentNullException("filename");
}
bool containedInvalidCharacters = false;
for (int i = 0; i < filename.Length; i++)
{
int n = filename[i];
if (
(n == 0x22) || // "
(n == 0x3c) || // <
(n == 0x3e) || // >
(n == 0x7c) || // |
(n == 0x3a) || // :
(n == 0x2a) || // *
(n == 0x3f) || // ?
(n == 0x5c) || // \
(n == 0x2f) || // /
(n < 0x20) // the control characters
)
{
containedInvalidCharacters = true;
}
}
return containedInvalidCharacters;
}
}
}
Ответ 11
Я использую следующее: он также проверяет расширение, что означает, что он может использоваться для тестирования, если указанный путь - это файл, но файл, который не существует.
private static bool isDirectory(string path)
{
bool result = true;
System.IO.FileInfo fileTest = new System.IO.FileInfo(path);
if (fileTest.Exists == true)
{
result = false;
}
else
{
if (fileTest.Extension != "")
{
result = false;
}
}
return result;
}
Ответ 12
Если вы хотите найти каталоги, в том числе те, которые отмечены как "скрытые" и "системные", попробуйте это (требуется .NET V4):
FileAttributes fa = File.GetAttributes(path);
if(fa.HasFlag(FileAttributes.Directory))
Ответ 13
using System;
using System.IO;
namespace FileOrDirectory
{
class Program
{
public static string FileOrDirectory(string path)
{
if (File.Exists(path))
return "File";
if (Directory.Exists(path))
return "Directory";
return "Path Not Exists";
}
static void Main()
{
Console.WriteLine("Enter The Path:");
string path = Console.ReadLine();
Console.WriteLine(FileOrDirectory(path));
}
}
}
Ответ 14
Мне это нужно, сообщения помогли, это сводится к одной строке, и если путь не является контуром вообще, он просто возвращает и завершает метод. В нем рассматриваются все вышеперечисленные проблемы, также не требуется конечная косая черта.
if (!Directory.Exists(@"C:\folderName")) return;
Ответ 15
Используя выбранный ответ на этот пост, я просмотрел комментарии и дал
@ŞafakGür, @Anthony и @Quinn Wilson за свои информационные биты, которые приводят меня к этому улучшенному ответу, который я написал и протестировал:
/// <summary>
/// Returns true if the path is a dir, false if it a file and null if it neither or doesn't exist.
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static bool? IsDirFile(this string path)
{
bool? result = null;
if(Directory.Exists(path) || File.Exists(path))
{
// get the file attributes for file or directory
var fileAttr = File.GetAttributes(path);
if (fileAttr.HasFlag(FileAttributes.Directory))
result = true;
else
result = false;
}
return result;
}
Ответ 16
После объединения предложений с другими ответами я понял, что придумал примерно то же самое, что ответ Ронни Оверби. Вот несколько тестов, чтобы указать на некоторые вещи, о которых нужно подумать:
- папки могут иметь "расширения":
C:\Temp\folder_with.dot
- файлы не могут заканчиваться разделителем каталогов (слэш)
- Существует технически два разделителя каталогов, которые являются специфичными для платформы, то есть могут быть или не быть слэшами (
Path.DirectorySeparatorChar
и Path.AltDirectorySeparatorChar
)
Тесты (Linqpad)
var paths = new[] {
// exists
@"C:\Temp\dir_test\folder_is_a_dir",
@"C:\Temp\dir_test\is_a_dir_trailing_slash\",
@"C:\Temp\dir_test\existing_folder_with.ext",
@"C:\Temp\dir_test\file_thats_not_a_dir",
@"C:\Temp\dir_test\notadir.txt",
// doesn't exist
@"C:\Temp\dir_test\dne_folder_is_a_dir",
@"C:\Temp\dir_test\dne_folder_trailing_slash\",
@"C:\Temp\dir_test\non_existing_folder_with.ext",
@"C:\Temp\dir_test\dne_file_thats_not_a_dir",
@"C:\Temp\dir_test\dne_notadir.txt",
};
foreach(var path in paths) {
IsFolder(path/*, false*/).Dump(path);
}
Результаты
C:\Temp\dir_test\folder_is_a_dir
True
C:\Temp\dir_test\is_a_dir_trailing_slash\
True
C:\Temp\dir_test\existing_folder_with.ext
True
C:\Temp\dir_test\file_thats_not_a_dir
False
C:\Temp\dir_test\notadir.txt
False
C:\Temp\dir_test\dne_folder_is_a_dir
True
C:\Temp\dir_test\dne_folder_trailing_slash\
True
C:\Temp\dir_test\non_existing_folder_with.ext
False (this is the weird one)
C:\Temp\dir_test\dne_file_thats_not_a_dir
True
C:\Temp\dir_test\dne_notadir.txt
False
Метод
/// <summary>
/// Whether the <paramref name="path"/> is a folder (existing or not);
/// optionally assume that if it doesn't "look like" a file then it a directory.
/// </summary>
/// <param name="path">Path to check</param>
/// <param name="assumeDneLookAlike">If the <paramref name="path"/> doesn't exist, does it at least look like a directory name? As in, it doesn't look like a file.</param>
/// <returns><c>True</c> if a folder/directory, <c>false</c> if not.</returns>
public static bool IsFolder(string path, bool assumeDneLookAlike = true)
{
// https://stackoverflow.com/questions/1395205/better-way-to-check-if-path-is-a-file-or-a-directory
// turns out to be about the same as /questions/25473/better-way-to-check-if-a-path-is-a-file-or-a-directory/185841#185841
// check in order of verisimilitude
// exists or ends with a directory separator -- files cannot end with directory separator, right?
if (Directory.Exists(path)
// use system values rather than assume slashes
|| path.EndsWith("" + Path.DirectorySeparatorChar)
|| path.EndsWith("" + Path.AltDirectorySeparatorChar))
return true;
// if we know for sure that it an actual file...
if (File.Exists(path))
return false;
// if it has an extension it should be a file, so vice versa
// although technically directories can have extensions...
if (!Path.HasExtension(path) && assumeDneLookAlike)
return true;
// only works for existing files, kinda redundant with `.Exists` above
//if( File.GetAttributes(path).HasFlag(FileAttributes.Directory) ) ...;
// no idea -- could return an 'indeterminate' value (nullable bool)
// or assume that if we don't know then it not a folder
return false;
}
Ответ 17
Не работает ли это?
var isFile = Regex.IsMatch(path, @"\w{1,}\.\w{1,}$");
Ответ 18
Это использует DirectoryInfo для получения атрибута
Dim newnode As TreeNode
Dim dirs As New DirectoryInfo(node.FullPath)
For Each dir As DirectoryInfo In dirs.GetDirectories()
If dir.Attributes = FileAttributes.Directory Then
Else
End If
Next
Это будет работать, если вы попытаетесь пройти через DirectoryInfo, пытаясь создать TreeView или прочитать TreeView