Format byte sizes and transfer rates
Orientation
ByteSize keeps a data quantity typed while the application parses, compares, adds, subtracts, and formats it. Numeric extensions create values without manual factors. ByteRate combines a size with a measurement interval for display as bytes, kilobytes, or larger units per second, minute, or hour.
Example
This program parses a size with an explicit provider, performs arithmetic, formats exact composite sizes, distinguishes bits from bytes, and formats a transfer rate:
using System.Globalization;
using Humanizer;
var culture = CultureInfo.GetCultureInfo("en-US");
CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = culture;
var parsed = ByteSize.Parse("1.5 KB", culture);
var combined = parsed + 512.Bytes();
var rate = 3.Megabytes()
.Per(TimeSpan.FromSeconds(2))
.Humanize("0.0", TimeUnit.Second, culture);
var composite = ByteSize.FromBits(81_937);
var decimalSize = ByteSize.FromBytes(1_000_000);
var binarySize = ByteSize.FromMebibytes(1);
var decimalRate = ByteSize.FromDecimalMegabytes(1)
.Per(TimeSpan.FromSeconds(1))
.HumanizeWithUnitSystem(ByteSizeUnitSystem.DecimalSi, culture: culture);
var binaryRate = binarySize
.Per(TimeSpan.FromSeconds(1))
.HumanizeWithUnitSystem(ByteSizeUnitSystem.BinaryIec, culture: culture);
AssertEqual(1536d, parsed.Bytes);
AssertEqual("2 KB", combined.Humanize("0", culture));
AssertEqual("1.5 MB/s", rate);
AssertEqual(true, ByteSize.TryParse("12 b", culture, out var bits));
AssertEqual(12L, bits.Bits);
AssertEqual(
"10 KB 2 B",
composite.HumanizeComposite(precision: 2, formatProvider: culture));
AssertEqual(
"10 KB 2 B 1 b",
composite.HumanizeComposite(precision: 3, formatProvider: culture));
AssertEqual(
"10 kilobytes, 2 bytes",
10_242.Bytes().HumanizeComposite(
formatProvider: culture,
separator: ", ",
toWords: true));
AssertEqual("-10 KB 2 B", (-10_242).Bytes().HumanizeComposite(formatProvider: culture));
AssertEqual("0 b", 0.Bytes().HumanizeComposite(formatProvider: culture));
AssertEqual(
"1 PB 1 TB 1 GB",
ByteSize.FromBytes(
ByteSize.BytesInPetabyte +
ByteSize.BytesInTerabyte +
ByteSize.BytesInGigabyte)
.HumanizeComposite(precision: 3, formatProvider: culture));
AssertEqual("1 MB", decimalSize.Format(ByteSizeUnitSystem.DecimalSi, formatProvider: culture));
AssertEqual("976.56 KiB", decimalSize.Format(ByteSizeUnitSystem.BinaryIec, formatProvider: culture));
AssertEqual(
"1 MB 1 kB 1 B",
ByteSize.FromBytes(1_001_001)
.HumanizeCompositeWithUnitSystem(
ByteSizeUnitSystem.DecimalSi,
precision: 3,
formatProvider: culture));
AssertEqual(
"1 MiB 1 KiB 1 B",
ByteSize.FromBytes(
ByteSize.BytesInMebibyte +
ByteSize.BytesInKibibyte +
1)
.HumanizeCompositeWithUnitSystem(
ByteSizeUnitSystem.BinaryIec,
precision: 3,
formatProvider: culture));
AssertEqual(decimalSize, ByteSize.ParseWithUnitSystem("1 MB", ByteSizeUnitSystem.DecimalSi, culture));
AssertEqual(binarySize, ByteSize.ParseWithUnitSystem("1 MiB", ByteSizeUnitSystem.BinaryIec, culture));
AssertEqual(false, ByteSize.TryParseWithUnitSystem("1 MB", ByteSizeUnitSystem.BinaryIec, culture, out _));
AssertEqual("1 MB/s", decimalRate);
AssertEqual("1 MiB/s", binaryRate);
Console.WriteLine("1.5 KB; 2 KB; 10 KB 2 B 1 b; 1.5 MB/s; 1 MB; 1 MB/s; 1 MiB/s");
static void AssertEqual<T>(T expected, T actual)
{
if (!EqualityComparer<T>.Default.Equals(expected, actual))
throw new InvalidOperationException($"Expected '{expected}', got '{actual}'.");
}
Create and format sizes
Use numeric extensions through Terabytes, or the corresponding
ByteSize.From... factories. Humanizer 4 also exposes decimal petabyte and
exabyte values plus explicit binary Kibibyte, Mebibyte, Gibibyte,
Tebibyte, and Pebibyte factories, properties, format tokens, parsing
symbols, and DataUnit values. Humanize chooses the largest whole unit and
accepts ordinary numeric format strings. ToFullWords uses full unit names.
For standards-explicit output, select a unit system per operation:
var size = ByteSize.FromBytes(1_000_000);
size.Format(ByteSizeUnitSystem.DecimalSi); // 1 MB
size.Format(ByteSizeUnitSystem.BinaryIec); // 976.56 KiB
size.FormatFullWords(ByteSizeUnitSystem.DecimalSi); // 1 megabyte
ByteSize.FromBytes(1_001_001)
.HumanizeCompositeWithUnitSystem(
ByteSizeUnitSystem.DecimalSi,
precision: 3); // 1 MB 1 kB 1 B
ByteSize.FromBytes(1_049_601)
.HumanizeCompositeWithUnitSystem(
ByteSizeUnitSystem.BinaryIec,
precision: 3); // 1 MiB 1 KiB 1 B
DecimalSi uses kB, MB, GB, TB, PB, and EB with powers of 1000.
BinaryIec uses KiB, MiB, GiB, TiB, and PiB with powers of 1024.
Legacy deliberately preserves Humanizer's established mixed behavior.
The choice is explicit and is not stored in ByteSize.
Decompose exact quantities
On Humanizer 4, HumanizeComposite walks the existing units from exabytes
through bits and returns up to precision nonzero parts. It preserves exact
byte and bit residuals while parts remain available: for example, 81,937 bits
becomes 10 KB 2 B 1 b at precision 3. Once the precision is reached, the
remaining residual is omitted rather than rounded.
The separator is literal and defaults to a space. Set toWords: true for
localized full unit names, and pass an IFormatProvider for numeric formatting
and the leading negative sign. Negative values have one sign before the first
part; zero is 0 b. Precision must be positive and the separator cannot be
null. Use HumanizeCompositeWithUnitSystem to decompose with one explicit
SI or IEC ladder throughout the result.
Parse user input
Parse throws for invalid input. TryParse accepts string or ReadOnlySpan<char> and returns false without throwing. Supply the same format provider used by the input field.
Use ParseWithUnitSystem, TryParseWithUnitSystem, or
TryParseSpanWithUnitSystem when factors must be unambiguous. Decimal parsing
accepts SI suffixes, while binary parsing accepts IEC suffixes and rejects
ambiguous KB, MB, GB, TB, PB, and EB suffixes.
Calculate rates
Call size.Per(interval).Humanize(format, TimeUnit.Second, culture). Rate display supports second, minute, and hour units.
Use HumanizeWithUnitSystem on ByteRate for explicit SI or IEC rate output.
Pitfall
Humanizer’s legacy KB, MB, GB, and TB values use binary multiples of
1024, while PB and EB use decimal SI factors. On Humanizer 4, prefer the
explicit IEC symbols KiB, MiB, GiB, TiB, and PiB when the binary
meaning must be unambiguous. The symbols b and B are intentionally
case-sensitive: lowercase is bits, uppercase is bytes. Other recognized unit
suffixes are case-insensitive. Fractional bits and values without a unit
suffix are invalid.
HumanizeComposite follows those same stored factors: PB and EB parts are
decimal SI, while TB and smaller legacy labels use binary multiples. It
preserves the legacy KB through TB symbols rather than relabeling them as
IEC units.
The existing APIs remain legacy APIs even when a value was created with a decimal or IEC factory. Pass the unit system again when formatting, parsing, humanizing a composite value, or displaying a rate; factory choice does not carry formatting provenance.
Construct rates with a positive, nonzero interval. Keep ByteSize as the model value; formatted output is not a serialization contract.
Version notes
Core ByteSize creation and formatting span the documented corpus. Petabyte,
exabyte, explicit IEC unit support, and HumanizeComposite are Humanizer 4
additions. Culture-aware ByteRate.Humanize appears in 2.13.14; earlier
snapshots need a reduced example or exclusion. The verified source runs
against the selected package.