Skip to main content
Version: 4.0 (next)

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:

Program.cs
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.