Содержание
При работе с файловой системой, все размеры файлов в 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.