Содержание
При работе с файловой системой, все размеры файлов в C# возвращаются в байтах. С одной стороны — это полностью оправданный и правильный подход, а, с другой стороны — пользователю не всегда удобно видеть перед собой огромные числа, обозначающие, например, объем свободного места на диске. Для предоставления информации о размере файла или объеме диска в удобном для пользователя виде (в Кб, Мб, Тб и т.д.) существует несколько подходов, например, можно написать свой метод перевода величин. Мы же сегодня рассмотрим класс, который реализует интерфейс IFormatProvider в C# и может использоваться при форматировании строк, содержащих размер файла.
Класс, реализующий IFormatProvider для вывода размера файла
Представленный ниже класс позволяет представлять размеры файлов в виде строки с определенными суффиксами (kB, MB, TB, GB и TB):
public class FileSizeFormatProvider : IFormatProvider, ICustomFormatter { public object GetFormat(Type formatType) { if (formatType == typeof(ICustomFormatter)) return this; return null; } private const string fileSizeFormat = "fs"; private const decimal OneKiloByte = 1024M; private const decimal OneMegaByte = OneKiloByte * 1024M; private const decimal OneGigaByte = OneMegaByte * 1024M; private const decimal OneTeraByte = OneMegaByte * 1024M * 1024M; public string Format(string format, object arg, IFormatProvider formatProvider) { if (format == null || !format.StartsWith(fileSizeFormat)) { return defaultFormat(format, arg, formatProvider); } if (arg is string) { return defaultFormat(format, arg, formatProvider); } decimal size; try { size = Convert.ToDecimal(arg); } catch (InvalidCastException) { return defaultFormat(format, arg, formatProvider); } string suffix; if (size > OneTeraByte) { size /= OneTeraByte; suffix = "TB"; } else if (size > OneGigaByte) { size /= OneGigaByte; suffix = "GB"; } else if (size > OneMegaByte) { size /= OneMegaByte; suffix = "MB"; } else if (size > OneKiloByte) { size /= OneKiloByte; suffix = "kB"; } else { suffix = " B"; } string precision = format.Substring(2); if (string.IsNullOrEmpty(precision)) precision = "2"; return string.Format("{0:N" + precision + "}{1}", size, suffix); } private static string defaultFormat(string format, object arg, IFormatProvider formatProvider) { IFormattable formattableArg = arg as IFormattable; if (formattableArg != null) { return formattableArg.ToString(format, formatProvider); } return arg.ToString(); } }
Достаточно добавить этот класс в свой проект и, в дальнейшем, его функциональность можно использовать для форматирования строк, используя описатель fs
.
Пример использования класса FileSizeFormatProvider
Рассмотрим пример использование класса FileSizeFormatProvider
для вывода информации о логических дисках. Первый вариант использования класса:
class Program { static void Main(string[] args) { DriveInfo[] drives = DriveInfo.GetDrives(); foreach (DriveInfo drive in drives) { Console.WriteLine($"Название: {drive.Name}"); Console.WriteLine($"Тип: {drive.DriveType}"); if (drive.IsReady) { Console.WriteLine(string.Format(new FileSizeFormatProvider(), "Объем диска: {0:fs}", drive.TotalSize)); Console.WriteLine(string.Format(new FileSizeFormatProvider(), "Свободное пространство: {0:fs}", drive.TotalFreeSpace)); Console.WriteLine($"Метка: {drive.VolumeLabel}"); } } } }
Можно немного упростить использование класса и написать свой метод расширения, например, так:
using System; using System.IO; namespace FileSystem { //метод расширеия для long public static class ExtensionMethods { public static string ToFileSize(this long l) { return string.Format(new FileSizeFormatProvider(), "{0:fs}", l); } } class Program { static void Main(string[] args) { DriveInfo[] drives = DriveInfo.GetDrives(); foreach (DriveInfo drive in drives) { Console.WriteLine($"Название: {drive.Name}"); Console.WriteLine($"Тип: {drive.DriveType}"); if (drive.IsReady) { Console.WriteLine($"Объем диска: {drive.TotalSize.ToFileSize()}") ; Console.WriteLine($"Свободное пространство: {drive.TotalFreeSpace.ToFileSize()}"); Console.WriteLine($"Метка: {drive.VolumeLabel}"); } } } } }
В любом случае, результат будет один и тот же:
Тип: Fixed
Объем диска: 111,12GB
Свободное пространство: 36,40GB
Метка:
Итого
Сегодня мы рассмотрели класс, реализующий интерфейс IFormatProvider
для форматирования размеров файлов в удобном для пользователя виде. Для использования класса его необходимо добавить в проект и, при необходимости, написать свой метод расширения.
При написании этой статьи использовались материалы с сайта stackoverflow.