GOOGLE ADS

воскресенье, 1 мая 2022 г.

Есть ли способ получить Environment.SpecialFolder из пути к файлу?

У меня есть требование, когда я хочу получить Environment.SpecialFolderзначение из пути к файлу.

Например -

string filePath = @"C:\Program Files (x86)\text.txt"
//SpecialFolder sf = GetSpecialFolderAssociatedWithPath(filePath); // sf will be ProgramFilesX86
//Need something similar

Я хочу в дальнейшем использовать sfдля создания другого пути, поэтому, если мы получим путь, соответствующий этому конкретному SpecialFolder, это тоже сработает.


Решение проблемы

Вы можете сделать это примерно так (при условии, что вы хотите получить фактическое значение перечисления для специальной папки):

public static Environment.SpecialFolder? FindSpecialFolder(string filePath)
{
filePath = Path.GetFullPath(filePath);
foreach (var folder in Enum.GetValues<Environment.SpecialFolder>())
{
string directory = Environment.GetFolderPath(folder);
if (directory.Length > 0 && filePath.StartsWith(directory, StringComparison.OrdinalIgnoreCase))
return folder;
}
return null;
}

Обратите внимание, что мне пришлось вернуть значение NULL, потому что Microsoft не следовала своим собственным рекомендациям и не включила в Environment.SpecialFolderперечисление специальное нулевое значение «Нет», которое я мог бы вернуть, чтобы указать «не найдено».

Использование будет примерно таким:

string filePath = @"C:\Program Files (x86)\text.txt";
var folder = FindSpecialFolder(filePath);
if (folder == null)
Console.WriteLine("No folder found");
else
Console.WriteLine(folder.Value);

Если вам нужны и путь, и значение перечисления, вы можете вернуть их оба в кортеже:

public static (Environment.SpecialFolder? specialFolder, string? directory) FindSpecialFolder(string filePath)
{
filePath = Path.GetFullPath(filePath);
foreach (var folder in Enum.GetValues<Environment.SpecialFolder>())
{
string directory = Environment.GetFolderPath(folder);
if (directory.Length > 0 && filePath.StartsWith(directory, StringComparison.OrdinalIgnoreCase))
return (folder, directory);
}
return default;
}

Который вы могли бы использовать как:

var folder = FindSpecialFolder(filePath);
if (folder.specialFolder == null)
Console.WriteLine("No folder found");
else
Console.WriteLine($"{folder.specialFolder.Value}: {folder.directory}");

На самом деле, возможно, что некоторые из специальных папок могут быть вложены в другие специальные папки, например, у вас могут быть:

C:\Path1\Path2
C:\Path1\Path2\Path3

В этом случае приведенный выше код вернет первый совпадающий путь, а не самый длинный; т.е. поиск "C:\Path1\Path2\Path3\SomeFile.txt"может вернуть специальную папку для "C:\Path1\Path2", а не папку для "C:\Path1\Path2\Path3".

Если вы хотите обработать эту возможность, вам нужно будет найти самый длинный соответствующий путь, например:

public static (Environment.SpecialFolder? specialFolder, string? directory) FindSpecialFolder(string filePath)
{
filePath = Path.GetFullPath(filePath);
int longest = 0;
Environment.SpecialFolder? longestFolder = null;
string? longestDir = null;
foreach (var folder in Enum.GetValues<Environment.SpecialFolder>())
{
string directory = Environment.GetFolderPath(folder);
if (directory.Length > longest && filePath.StartsWith(directory, StringComparison.OrdinalIgnoreCase))
{
longestDir = directory;
longestFolder = folder;
longest = directory.Length;
}
}
return (longestFolder, longestDir);
}

И используйте его как:

var folder = FindSpecialFolder(filePath);
if (folder.specialFolder == null)
Console.WriteLine("No folder found");
else
Console.WriteLine($"{folder.specialFolder.Value}: {folder.directory}");

Еще одна вещь, о которой следует помнить, это то, что несколько специальных папок могут иметь один и тот же путь. В этом случае их невозможно различить, поэтому код просто вернет первое найденное совпадение.

Также обратите внимание на использование, filePath = Path.GetFullPath(filePath);чтобы обеспечить преобразование относительных путей в абсолютные, иначе сопоставление, скорее всего, не сработает.

Комментариев нет:

Отправить комментарий

Laravel Datatable addColumn returns ID of one record only

Я пытаюсь использовать Yajra Datatable для интеграции DataTable на свой веб-сайт. Я смог отобразить таблицу, но столкнулся с проблемой. В по...