Как получить размер удобочитаемого файла в аббревиатуре байтов с помощью .NET?

Как получить размер удобочитаемого файла в аббревиатуре байтов с помощью .NET?

Пример : введите вход 7,326,629 и отобразите 6,98 МБ

Это не самый эффективный способ сделать это, но его легче читать, если вы не знакомы с математикой журналов и должны быть достаточно быстрыми для большинства сценариев.

string[] sizes = { "B", "KB", "MB", "GB", "TB" }; double len = new FileInfo(filename).Length; int order = 0; while (len >= 1024 && order < sizes.Length - 1) { order++; len = len/1024; } // Adjust the format string to your preferences. For example "{0:0.#}{1}" would // show a single decimal place, and no space. string result = String.Format("{0:0.##} {1}", len, sizes[order]); 

используя Log для решения проблемы ….

 static String BytesToString(long byteCount) { string[] suf = { "B", "KB", "MB", "GB", "TB", "PB", "EB" }; //Longs run out around EB if (byteCount == 0) return "0" + suf[0]; long bytes = Math.Abs(byteCount); int place = Convert.ToInt32(Math.Floor(Math.Log(bytes, 1024))); double num = Math.Round(bytes / Math.Pow(1024, place), 1); return (Math.Sign(byteCount) * num).ToString() + suf[place]; } 

Также в c #, но должна быть оснастка для преобразования. Также я округлился до 1 десятичной точки для удобочитаемости.

В основном Определите количество знаков после запятой в Base 1024, а затем разделите их на 1024 символа decimalplaces.

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

 Console.WriteLine(BytesToString(9223372036854775807)); //Results in 8EB Console.WriteLine(BytesToString(0)); //Results in 0B Console.WriteLine(BytesToString(1024)); //Results in 1KB Console.WriteLine(BytesToString(2000000)); //Results in 1.9MB Console.WriteLine(BytesToString(-9023372036854775807)); //Results in -7.8EB 

Edit: Было указано, что я пропустил math.floor, поэтому я включил его. (Convert.ToInt32 использует округление, а не усечение, и именно поэтому пол необходим.) Спасибо за улов.

Edit2: Было несколько комментариев об отрицательных размерах и размерах в 0 байт, поэтому я обновил эти два случая.

Здесь протестирована и значительно оптимизированная версия запрошенной функции:

C # Человеческий читаемый размер файла – Оптимизированная функция

Исходный код:

 // Returns the human-readable file size for an arbitrary, 64-bit file size // The default format is "0.### XB", eg "4.2 KB" or "1.434 GB" public string GetBytesReadable(long i) { // Get absolute value long absolute_i = (i < 0 ? -i : i); // Determine the suffix and readable value string suffix; double readable; if (absolute_i >= 0x1000000000000000) // Exabyte { suffix = "EB"; readable = (i >> 50); } else if (absolute_i >= 0x4000000000000) // Petabyte { suffix = "PB"; readable = (i >> 40); } else if (absolute_i >= 0x10000000000) // Terabyte { suffix = "TB"; readable = (i >> 30); } else if (absolute_i >= 0x40000000) // Gigabyte { suffix = "GB"; readable = (i >> 20); } else if (absolute_i >= 0x100000) // Megabyte { suffix = "MB"; readable = (i >> 10); } else if (absolute_i >= 0x400) // Kilobyte { suffix = "KB"; readable = i; } else { return i.ToString("0 B"); // Byte } // Divide by 1024 to get fractional value readable = (readable / 1024); // Return formatted number with suffix return readable.ToString("0.### ") + suffix; } 
 [DllImport ( "Shlwapi.dll", CharSet = CharSet.Auto )] public static extern long StrFormatByteSize ( long fileSize , [MarshalAs ( UnmanagedType.LPTStr )] StringBuilder buffer , int bufferSize ); ///  /// Converts a numeric value into a string that represents the number expressed as a size value in bytes, kilobytes, megabytes, or gigabytes, depending on the size. ///  /// The numeric value to be converted. /// the converted string public static string StrFormatByteSize (long filesize) { StringBuilder sb = new StringBuilder( 11 ); StrFormatByteSize( filesize, sb, sb.Capacity ); return sb.ToString(); } 

От: http://www.pinvoke.net/default.aspx/shlwapi/StrFormatByteSize.html

Еще один способ обмануть его, без каких-либо петель и с поддержкой отрицательного размера (имеет смысл для таких вещей, как дельта файла):

 public static class Format { static string[] sizeSuffixes = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" }; public static string ByteSize(long size) { Debug.Assert(sizeSuffixes.Length > 0); const string formatTemplate = "{0}{1:0.#} {2}"; if (size == 0) { return string.Format(formatTemplate, null, 0, sizeSuffixes[0]); } var absSize = Math.Abs((double)size); var fpPower = Math.Log(absSize, 1000); var intPower = (int)fpPower; var iUnit = intPower >= sizeSuffixes.Length ? sizeSuffixes.Length - 1 : intPower; var normSize = absSize / Math.Pow(1000, iUnit); return string.Format( formatTemplate, size < 0 ? "-" : null, normSize, sizeSuffixes[iUnit]); } } 

И вот набор тестов:

 [TestFixture] public class ByteSize { [TestCase(0, Result="0 B")] [TestCase(1, Result = "1 B")] [TestCase(1000, Result = "1 KB")] [TestCase(1500000, Result = "1.5 MB")] [TestCase(-1000, Result = "-1 KB")] [TestCase(int.MaxValue, Result = "2.1 GB")] [TestCase(int.MinValue, Result = "-2.1 GB")] [TestCase(long.MaxValue, Result = "9.2 EB")] [TestCase(long.MinValue, Result = "-9.2 EB")] public string Format_byte_size(long size) { return Format.ByteSize(size); } } 

Мне нравится использовать следующий метод (он поддерживает до терабайт, чего достаточно для большинства случаев, но его можно легко расширить):

 private string GetSizeString(long length) { long B = 0, KB = 1024, MB = KB * 1024, GB = MB * 1024, TB = GB * 1024; double size = length; string suffix = nameof(B); if (length >= TB) { size = Math.Round((double)length / TB, 2); suffix = nameof(TB); } else if (length >= GB) { size = Math.Round((double)length / GB, 2); suffix = nameof(GB); } else if (length >= MB) { size = Math.Round((double)length / MB, 2); suffix = nameof(MB); } else if (length >= KB) { size = Math.Round((double)length / KB, 2); suffix = nameof(KB); } return $"{size} {suffix}"; } 

Имейте в виду, что это написано для C # 6.0 (2015), поэтому для более ранних версий может потребоваться небольшое редактирование.

 int size = new FileInfo( filePath ).Length / 1024; string humanKBSize = string.Format( "{0} KB", size ); string humanMBSize = string.Format( "{0} MB", size / 1024 ); string humanGBSize = string.Format( "{0} GB", size / 1024 / 1024 ); 

Оформить заказ в библиотеке ByteSize . Это System.TimeSpan для байтов!

Он обрабатывает преобразование и форматирование для вас.

 var maxFileSize = ByteSize.FromKiloBytes(10); maxFileSize.Bytes; maxFileSize.MegaBytes; maxFileSize.GigaBytes; 

Он также выполняет строковое представление и синтаксический анализ.

 // ToString ByteSize.FromKiloBytes(1024).ToString(); // 1 MB ByteSize.FromGigabytes(.5).ToString(); // 512 MB ByteSize.FromGigabytes(1024).ToString(); // 1 TB // Parsing ByteSize.Parse("5b"); ByteSize.Parse("1.55B"); 
 string[] suffixes = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" }; int s = 0; long size = fileInfo.Length; while (size >= 1024) { s++; size /= 1024; } string humanReadable = String.Format("{0} {1}", size, suffixes[s]); 

Если вы пытаетесь сопоставить размер, как показано в подробном представлении проводника Windows, это код, который вы хотите:

 [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)] private static extern long StrFormatKBSize( long qdw, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder pszBuf, int cchBuf); public static string BytesToString(long byteCount) { var sb = new StringBuilder(32); StrFormatKBSize(byteCount, sb, sb.Capacity); return sb.ToString(); } 

Это будет не только соответствовать Explorer точно, но также предоставит строки, переведенные для вас, и сопоставьте различия в версиях Windows (например, в Win10, K = 1000 и предыдущих версиях K = 1024).

Смесь всех решений 🙂

  ///  /// Converts a numeric value into a string that represents the number expressed as a size value in bytes, /// kilobytes, megabytes, or gigabytes, depending on the size. ///  /// The numeric value to be converted. /// The converted string. public static string FormatByteSize(double fileSize) { FileSizeUnit unit = FileSizeUnit.B; while (fileSize >= 1024 && unit < FileSizeUnit.YB) { fileSize = fileSize / 1024; unit++; } return string.Format("{0:0.##} {1}", fileSize, unit); } ///  /// Converts a numeric value into a string that represents the number expressed as a size value in bytes, /// kilobytes, megabytes, or gigabytes, depending on the size. ///  ///  /// The converted string. public static string FormatByteSize(FileInfo fileInfo) { return FormatByteSize(fileInfo.Length); } } public enum FileSizeUnit : byte { B, KB, MB, GB, TB, PB, EB, ZB, YB } 

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

 7.Bits().ToString(); // 7 b 8.Bits().ToString(); // 1 B (.5).Kilobytes().Humanize(); // 512 B (1000).Kilobytes().ToString(); // 1000 KB (1024).Kilobytes().Humanize(); // 1 MB (.5).Gigabytes().Humanize(); // 512 MB (1024).Gigabytes().ToString(); // 1 TB 

http://humanizr.net/#bytesize

https://github.com/MehdiK/Humanizer

Я предполагаю, что вы ищете «1,4 МБ» вместо «1468006 байтов»?

Я не думаю, что есть встроенный способ сделать это в .NET. Вам нужно просто выяснить, какой блок подходит, и отформатировать его.

Редактирование: Вот пример кода для этого:

http://www.codeproject.com/KB/cpp/formatsize.aspx

Как насчет некоторой рекурсии:

 private static string ReturnSize(double size, string sizeLabel) { if (size > 1024) { if (sizeLabel.Length == 0) return ReturnSize(size / 1024, "KB"); else if (sizeLabel == "KB") return ReturnSize(size / 1024, "MB"); else if (sizeLabel == "MB") return ReturnSize(size / 1024, "GB"); else if (sizeLabel == "GB") return ReturnSize(size / 1024, "TB"); else return ReturnSize(size / 1024, "PB"); } else { if (sizeLabel.Length > 0) return string.Concat(size.ToString("0.00"), sizeLabel); else return string.Concat(size.ToString("0.00"), "Bytes"); } } 

Затем вы называете это:

 return ReturnSize(size, string.Empty); 

 public static string ToBytesCount(this long bytes) { int unit = 1024; if (bytes < unit) return bytes + " o"; int exp = (int)(Math.Log(bytes) / Math.Log(unit)); return string.Format("{0:##.##} {1}o", bytes / Math.Pow(unit, exp), "KMGTPE"[exp - 1]); } 

Мои 2 цента:

  • Префикс для килобайта – kB (нижний регистр K)
  • Поскольку эти функции предназначены для представления, нужно предоставить культуру, например: string.Format(CultureInfo.CurrentCulture, "{0:0.##} {1}", fileSize, unit);
  • В зависимости от контекста килобайт может быть 1000 или 1024 байта . То же самое касается MB, GB и т. Д.

Еще один подход, для чего он стоит. Мне понравилось оптимизированное решение @humbads, упомянутое выше, поэтому скопировали принцип, но я реализовал его несколько иначе.

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

Что касается подразделений, я не думаю, что я когда-либо говорил «Kibibyte» или «Mebibyte» в своей жизни, и хотя я скептически отношусь к таким принудительным, а не развитым стандартам, я полагаю, что это позволит избежать путаницы в долгосрочной перспективе ,

 public static class LongExtensions { private static readonly long[] numberOfBytesInUnit; private static readonly Func[] bytesToUnitConverters; static LongExtensions() { numberOfBytesInUnit = new long[6] { 1L << 10, // Bytes in a Kibibyte 1L << 20, // Bytes in a Mebibyte 1L << 30, // Bytes in a Gibibyte 1L << 40, // Bytes in a Tebibyte 1L << 50, // Bytes in a Pebibyte 1L << 60 // Bytes in a Exbibyte }; // Shift the long (integer) down to 1024 times its number of units, convert to a double (real number), // then divide to get the final number of units (units will be in the range 1 to 1023.999) Func FormatAsProportionOfUnit = (bytes, shift) => (((double)(bytes >> shift)) / 1024).ToString("0.###"); bytesToUnitConverters = new Func[7] { bytes => bytes.ToString() + " B", bytes => FormatAsProportionOfUnit(bytes, 0) + " KiB", bytes => FormatAsProportionOfUnit(bytes, 10) + " MiB", bytes => FormatAsProportionOfUnit(bytes, 20) + " GiB", bytes => FormatAsProportionOfUnit(bytes, 30) + " TiB", bytes => FormatAsProportionOfUnit(bytes, 40) + " PiB", bytes => FormatAsProportionOfUnit(bytes, 50) + " EiB", }; } public static string ToReadableByteSizeString(this long bytes) { if (bytes < 0) return "-" + Math.Abs(bytes).ToReadableByteSizeString(); int counter = 0; while (counter < numberOfBytesInUnit.Length) { if (bytes < numberOfBytesInUnit[counter]) return bytesToUnitConverters[counter](bytes); counter++; } return bytesToUnitConverters[counter](bytes); } } 

Как решение @ NET3. Используйте shift вместо деления, чтобы проверить диапазон bytes , потому что деление требует больше затрат на процессор.

 private static readonly string[] UNITS = new string[] { "B", "KB", "MB", "GB", "TB", "PB", "EB" }; public static string FormatSize(ulong bytes) { int c = 0; for (c = 0; c < UNITS.Length; c++) { ulong m = (ulong)1 << ((c + 1) * 10); if (bytes < m) break; } double n = bytes / (double)((ulong)1 << (c * 10)); return string.Format("{0:0.##} {1}", n, UNITS[c]); } 
  • Свойство привязки для управления в Winforms
  • Как отключить элемент в элементе управления listview в .net 3.5
  • Как сгладить вложенные объекты с выражением linq
  • Скрыть одиночную форму при запуске
  • Скрытие и отображение вкладок в tabControl
  • Зачем использовать String.Format?
  • возвращать только цифры 0-9 из строки
  • Определите, является ли общий параметр нулевым типом
  • Самый быстрый способ удаления пустых строк и столбцов из файлов Excel с помощью Interop
  • Как получить ВСЕ дочерние элементы формы формы Windows Forms определенного типа (Button / Textbox)?
  • HTTP GET в VB.NET
  • Давайте будем гением компьютера.