descriptionStorage units according to ISO IEC 80000-13:2008
repository URLhttps://github.com/sebhoss/storage-units.git
ownerrepoorcz@shoss.de
last changeMon, 11 Mar 2024 11:45:24 +0000 (11 12:45 +0100)
last refreshSat, 11 May 2024 02:58:31 +0000 (11 04:58 +0200)
content tags
add:
README.md

Storage-Units Chat

Storage units according to ISO IEC 80000-13:2008 implemented in Java.

Features

Available Units

NameSymbolExponentialAbsolute
ByteB20 Byte1 Byte
KibibyteKiB210 Byte1 024 Byte
MebibyteMiB220 Byte1 048 576 Byte
GibibyteGiB230 Byte1 073 741 824 Byte
TebibyteTiB240 Byte1 099 511 627 776 Byte
PebibytePiB250 Byte1 125 899 906 842 624 Byte
ExbibyteEiB260 Byte1 152 921 504 606 846 976 Byte
ZebibyteZiB270 Byte1 180 591 620 717 411 303 424 Byte
YobibyteYiB280 Byte1 208 925 819 614 629 174 706 176 Byte
RobibyteRiB290 Byte1 237 940 039 285 380 274 899 124 224 Byte
QubibyteQiB2100 Byte1 267 650 600 228 229 401 496 703 205 376 Byte
NameSymbolExponentialAbsolute
ByteB100 Byte1 Byte
KilobyteKB103 Byte1 000 Byte
MegabyteMB106 Byte1 000 000 Byte
GigabyteGB109 Byte1 000 000 000 Byte
TerabyteTB1012 Byte1 000 000 000 000 Byte
PetabytePB1015 Byte1 000 000 000 000 000 Byte
ExabyteEB1018 Byte1 000 000 000 000 000 000 Byte
ZettabyteZB1021 Byte1 000 000 000 000 000 000 000 Byte
YottabyteYB1024 Byte1 000 000 000 000 000 000 000 000 Byte
RonnabyteRB1027 Byte1 000 000 000 000 000 000 000 000 000 Byte
QuettabyteQB1030 Byte1 000 000 000 000 000 000 000 000 000 000 Byte

Usage

Factories

Each unit implements a Byte-based static factory method (valueOf(BigInteger) or valueOf(long)) that can be used to represent a given number of bytes in a specific unit. Note that Long.MAX_VALUE == 8 Exabyte, thus use BigInteger if you want to work with anything bigger than a eight Exabyte. When in doubt, always use BigInteger.

// 'long' based
Kilobyte unit = Kilobyte.valueOf(500)                           // 500 Byte or "0.50 kB"
Kibibyte unit = Kibibyte.valueOf(512)                           // 512 Byte or "0.50 KiB"

Megabyte unit = Megabyte.valueOf(1_000_000)                     // 1 000 000 Byte or "1.00 MB"
Mebibyte unit = Mebibyte.valueOf(1_048_576)                     // 1 048 576 Byte or "1.00 MiB"

// 'BigInteger' based
Kilobyte unit = Kilobyte.valueOf(BigInteger.valueOf(500))       // 500 Byte or "0.50 kB"
Kibibyte unit = Kibibyte.valueOf(BigInteger.valueOf(512))       // 512 Byte or "0.50 KiB"

Megabyte unit = Megabyte.valueOf(BigInteger.valueOf(1000000))   // 1 000 000 Byte or "1.00 MB"
Mebibyte unit = Mebibyte.valueOf(BigInteger.valueOf(1_048_576)) // 1 048 576 Byte or "1.00 MB"

The StorageUnits class offers three factory methods that automatically pick the best-matching unit for a given number of bytes.

Binary Units

// 'long' based
StorageUnit<?> unit = StorageUnits.binaryValueOf(256)                         // Kibibyte (0.25 KiB)
StorageUnit<?> unit = StorageUnits.binaryValueOf(1048576)                     // Mebibyte (1.00 MiB)

// 'BigInteger' based
StorageUnit<?> unit = StorageUnits.binaryValueOf(BigInteger.valueOf(256))     // Kibibyte (0.25 MiB)
StorageUnit<?> unit = StorageUnits.binaryValueOf(BigInteger.valueOf(1048576)) // Mebibyte (1.00 MiB)

Decimal Units

// 'long' based
StorageUnit<?> unit = StorageUnits.decimalValueOf(120000)                      // Kilobyte (120.00 kB)
StorageUnit<?> unit = StorageUnits.decimalValueOf(1000000)                     // Megabyte (1.00 MB)

// 'BigInteger' based
StorageUnit<?> unit = StorageUnits.decimalValueOf(BigInteger.valueOf(120000))  // Kilobyte (120.00 kB)
StorageUnit<?> unit = StorageUnits.decimalValueOf(BigInteger.valueOf(1000000)) // Megabyte (1.00 MB)

Additionally high-level factory methods are also available in the StorageUnits class.

import static wtf.metio.storageunits.model.StorageUnits.*;

Kibibyte unit = kibibyte(1)   // 1 024 Byte
Mebibyte unit = mebibyte(1)   // 1 048 576 Byte
Gibibyte unit = gibibyte(1)   // 1 073 741 824 Byte
Tebibyte unit = tebibyte(1)   // 1 099 511 627 776 Byte
Pebibyte unit = pebibyte(1)   // 1 125 899 906 842 624 Byte
Exbibyte unit = exbibyte(1)   // 1 152 921 504 606 846 976 Byte
Zebibyte unit = zebibyte(1)   // 1 180 591 620 717 411 303 424 Byte
Yobibyte unit = yobibyte(1)   // 1 208 925 819 614 629 174 706 176 Byte
Robibyte unit = robibyte(1)   // 1 237 940 039 285 380 274 899 124 224 Byte
Qubibyte unit = qubibyte(1)   // 1 267 650 600 228 229 401 496 703 205 376 Byte

Kilobyte unit = kilobyte(1)     // 1 000 Byte
Megabyte unit = megabyte(1)     // 1 000 000 Byte
Gigabyte unit = gigabyte(1)     // 1 000 000 000 Byte
Terabyte unit = terabyte(1)     // 1 000 000 000 000 Byte
Petabyte unit = petabyte(1)     // 1 000 000 000 000 000 Byte
Exabyte unit = exabyte(1)       // 1 000 000 000 000 000 000 Byte
Zettabyte unit = zettabyte(1)   // 1 000 000 000 000 000 000 000 Byte
Yottabyte unit = yottabyte(1)   // 1 000 000 000 000 000 000 000 000 Byte
Ronnabyte unit = ronnabyte(1)   // 1 000 000 000 000 000 000 000 000 000 Byte
Quettabyte unit = quettabyte(1) // 1 000 000 000 000 000 000 000 000 000 000 Byte

Add, Subtract, Multiply, Divide

Each unit implements the basic four math operations. All operations retain their original type, e.g. [Kilobyte] + [Megabyte] = [Kilobyte]

import static wtf.metio.storageunits.model.StorageUnits.*;

kilobyte(4).add(kilobyte(8))        // 4 Kilobyte + 8 Kilobyte = 12 Kilobyte = 12 000 Byte
kibibyte(1).add(1024)               // 1 Kibibyte + 1 024 Byte = 2 Kibibyte = 2 048 Byte
kibibyte(1).subtract(24)            // 1 024 Byte - 24 Byte = 1 000 Byte
megabyte(5).subtract(kilobyte(500)) // 5 Megabyte - 500 Kilobyte = 4.5 Megabyte = 4 500 Kilobyte = 4 500 000 Byte
gigabyte(1).multiply(5)             // 1 Gigabyte times 5 = 5 Gigabyte
terabyte(1).divide(5)               // 1 Terabyte divided by 5 = 0.2 Terabyte = 200 Gigabyte

Comparison & Equality

Each unit is comparable to each other unit.

import static wtf.metio.storageunits.model.StorageUnits.*;

kibibyte(1024).compareTo(mebibyte(1)) == 0 // true
kibibyte(1000).compareTo(mebibyte(1)) == 0 // false
petabyte(3).compareTo(terabyte(3000)) == 0 // true

megabyte(1000).equals(gigabyte(1))         // true
megabyte(1024).equals(gigabyte(1))         // false
terabyte(12).equals(gigabyte(12000))       // true

Formatting

Each unit prints a human-readable string, representing the amount of bytes in the given unit using the symbol specified in ISO IEC 80000-13:2008.

import static wtf.metio.storageunits.model.StorageUnits.*;

// default pattern '0.00'
terabyte(2).toString()                         // "2.00 TB"
gigabyte(1).add(megabyte(200)).toString()      // "1.20 GB"
petabyte(1).subtract(terabyte(250)).toString() // "0.75 PB"

// use custom pattern
kilobyte(212345).toString("0.0")                                    // "212345.0 kB"
gibibyte(2123458).asTebibyte().toString("#,###.000")                // "2,073.689 TiB"
kilobyte(120).asMegabyte().add(gigabyte(1)).toString("#,##0.00000") // "1,000.12000 MB"

// use custom pattern with specific Locale
kilobyte(212345).toString("0.0", Locale.GERMAN)                     // "212345,0 kB"
gibibyte(2123458).asTebibyte().toString("#,###.000", Locale.GERMAN) // "2.073,689 TiB"

// use custom format
Format customFormat = new DecimalFormat("#.00000");
terabyte(4).asTebibyte().toString(customFormat) // "3.63798 TiB"

// without creating unit type first
long numberOfBytes = 1_000_000_000_000_000L;
formatAsPetabyte(numberOfBytes) // "1.00 PB"
formatAsTerabyte(numberOfBytes) // "1000.00 TB"
formatAsPebibyte(numberOfBytes) // "0.89 PiB"

// use custom pattern
formatAsTerabyte(numberOfBytes, "#0.#####") // "1000 TB"
formatAsPebibyte(numberOfBytes, "#0.#####") // "0.88818 PiB"

// use custom pattern with specific Locale
formatAsTerabyte(numberOfBytes, "#0.#####", Locale.GERMAN) // "1000 TB"
formatAsPebibyte(numberOfBytes, "#0.#####", Locale.GERMAN) // "0,88818 PiB"

// use custom format
formatAsTerabyte(numberOfBytes, customFormat) // "1000.00000 TB"
formatAsPebibyte(numberOfBytes, customFormat) // ".88818 PiB"

Conversions

Each unit can be converted to each other unit without loss of information.

import static wtf.metio.storageunits.model.StorageUnits.*;

Megabyte unit = kilobyte(1000).asMegabyte() // "1.00 MB"
Kilobyte unit = gigabyte(12).asKilobyte()   // "12000000.00 kB"
Gigabyte unit = terabyte(1).asGigabyte()    // "1000.00 GB"

// convert to best-match
kilobyte(1100).asBestMatchingUnit()          // "1.10 MB"
kilobyte(1100).asBestMatchingBinaryUnit()    // "1.05 MiB"
kilobyte(1100).asBestMatchingDecimalUnit()   // "1.10 MB"

Each unit can be expressed as a fraction of another unit (precise up to 24 decimal places)

import static wtf.metio.storageunits.model.StorageUnits.*;

BigDecimal kilobytes = megabyte(1).inKilobyte()  // 1 000
BigInteger bytes = kibibyte(2).inByte()          // 2 048
BigDecimal terabytes = gigabyte(15).inTerabyte() // 0.015

Serialization/Converters/Mappers

Multiple custom serializers, converters, and mappers are available for all storage units.

Dozer

Use a Dozer converter like this:

import static wtf.metio.storageunits.dozer.*;

DozerBeanMapperBuilder.create()
        .withCustomConverter(new BigIntegerBinaryStorageUnitConverter())
        .withCustomConverter(new BigIntegerDecimalStorageUnitConverter())
        .withCustomConverter(new LongBinaryStorageUnitConverter())
        .withCustomConverter(new LongDecimalStorageUnitConverter())
        .build();

Use any of the three converters like this:

import static wtf.metio.storageunits.eclipselink.*;

@Entity
public class HardDisk implements Serializable {

    @Basic
    @Converter (
        name="binaryConverter",
        converterClass=BinaryStorageUnitConverter.class
    )
    @Convert("binaryConverter")
    public StorageUnit<?> getFreeSize() {
        return freeSize;
    }

    @Basic
    @Converter (
        name="decimalConverter",
        converterClass=DecimalyStorageUnitConverter.class
    )
    @Convert("decimalConverter")
    public StorageUnit<?> getTotalSize() {
        return totalSize;
    }

}

GSON

Use a GSON serializer/deserializer like this:

import static wtf.metio.storageunits.gson.*;

new GsonBuilder()
        .registerTypeHierarchyAdapter(StorageUnit.class, new StorageUnitSerializer())
        .registerTypeHierarchyAdapter(StorageUnit.class, new BinaryStorageUnitDeserializer())
        .registerTypeHierarchyAdapter(StorageUnit.class, new DecimalStorageUnitDeserializer())
        .create();

Jackson

Use the provided StorageUnitModule like this:

import static wtf.metio.storageunits.jackson.*;

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new StorageUnitModule()); // defaults to binary units
objectMapper.registerModule(new StorageUnitModule(StorageUnitModule.PreferredUnitType.BINARY));
objectMapper.registerModule(new StorageUnitModule(StorageUnitModule.PreferredUnitType.DECIMAL));

Jakarta

Use the provided AttributeConverters like this:

import static wtf.metio.storageunits.jakarta.*;

@Entity
public class HardDisk implements Serializable {

    @Convert(converter = BinaryStorageUnitConverter.class)
    public StorageUnit<?> getFreeSize() {
        return freeSize;
    }

    @Convert(converter = DecimalStorageUnitConverter.class)
    public StorageUnit<?> getTotalSize() {
        return totalSize;
    }

}

MapStruct

Use any of the available mappers like this:

import static wtf.metio.storageunits.mapstruct.*;

@Mapper( uses = BigIntegerToBinaryUnitMapper.class )
public interface MovieMapper {

     DestinationType toDestination(SourceType sourceValue);

}

ModelMapper

Use any of the available converters like this:

import static wtf.metio.storageunits.modelmapper.*;

modelMapper.addConverter(new BigIntegerToBinaryUnitConverter());
modelMapper.addConverter(new BigIntegerToDecimalUnitConverter());
modelMapper.addConverter(new LongToBinaryUnitConverter());
modelMapper.addConverter(new LongToDecimalUnitConverter());
modelMapper.addConverter(new StorageUnitToBigIntegerConverter());

MongoDB

Use any of the three codecs like this:

import static wtf.metio.storageunits.mongodb.*;

CodecRegistry binaryRegistry = CodecRegistries.fromCodecs(new BinaryStorageUnitCodec(), ...);
CodecRegistry decimalRegistry = CodecRegistries.fromCodecs(new DecimalStorageUnitCodec(), ...);

Orika

Use any of the provided converters like this:

import static wtf.metio.storageunits.orika.*;

ConverterFactory converterFactory = mapperFactory.getConverterFactory();
converterFactory.registerConverter(new BinaryStorageUnitConverter());
converterFactory.registerConverter(new DecimalStorageUnitConverter());

Integration

To use this project just declare the following dependency inside your POM:

<dependencies>
    <dependency>
        <groupId>wtf.metio.storage-units</groupId>
        <artifactId>storage-units-model</artifactId>
        <version>${version.storage-units}</version>
    </dependency>

    <!-- Dozer ONLY -->
    <dependency>
        <groupId>wtf.metio.storage-units</groupId>
        <artifactId>storage-units-dozer</artifactId>
        <version>${version.storage-units}</version>
    </dependency>
    <!-- Dozer ONLY -->

    <!-- EclipseLink ONLY -->
    <dependency>
        <groupId>wtf.metio.storage-units</groupId>
        <artifactId>storage-units-eclipselink</artifactId>
        <version>${version.storage-units}</version>
    </dependency>
    <!-- EclipseLink ONLY -->

    <!-- GSON ONLY -->
    <dependency>
        <groupId>wtf.metio.storage-units</groupId>
        <artifactId>storage-units-gson</artifactId>
        <version>${version.storage-units}</version>
    </dependency>
    <!-- GSON ONLY -->

    <!-- Jackson ONLY -->
    <dependency>
        <groupId>wtf.metio.storage-units</groupId>
        <artifactId>storage-units-jackson</artifactId>
        <version>${version.storage-units}</version>
    </dependency>
    <!-- Jackson ONLY -->

    <!-- Jakarta ONLY -->
    <dependency>
        <groupId>wtf.metio.storage-units</groupId>
        <artifactId>storage-units-jakarta</artifactId>
        <version>${version.storage-units}</version>
    </dependency>
    <!-- Jakarta ONLY -->

    <!-- MapStruct ONLY -->
    <dependency>
        <groupId>wtf.metio.storage-units</groupId>
        <artifactId>storage-units-mapstruct</artifactId>
        <version>${version.storage-units}</version>
    </dependency>
    <!-- MapStruct ONLY -->

    <!-- ModelMapper ONLY -->
    <dependency>
        <groupId>wtf.metio.storage-units</groupId>
        <artifactId>storage-units-modelmapper</artifactId>
        <version>${version.storage-units}</version>
    </dependency>
    <!-- ModelMapper ONLY -->

    <!-- MongoDB ONLY -->
    <dependency>
        <groupId>wtf.metio.storage-units</groupId>
        <artifactId>storage-units-mongodb</artifactId>
        <version>${version.storage-units}</version>
    </dependency>
    <!-- MongoDB ONLY -->

    <!-- Orika ONLY -->
    <dependency>
        <groupId>wtf.metio.storage-units</groupId>
        <artifactId>storage-units-orika</artifactId>
        <version>${version.storage-units}</version>
    </dependency>
    <!-- Orika ONLY -->
</dependencies>

Replace ${version.storage-units} with the latest release.

Reference

Originally inspired by Twitters util package.

Alternatives

shortlog
2024-03-11 dependabot... Bump softprops/action-gh-release from 1 to 2 (#62)main
2024-02-28 dependabot... Bump fsfe/reuse-action from 2 to 3 (#61)
2024-02-01 dependabot... Bump peter-evans/create-pull-request from 5 to 6 (#60)
2023-12-19 Sebastian Hoßupdate workflows (#58)2023.12.20
2023-12-14 dependabot... Bump github/codeql-action from 2 to 3
2023-12-05 sebhossUpdate parent to latest version2023.12.5
2023-11-30 dependabot... Bump actions/setup-java from 3 to 4
2023-11-13 dependabot... Bump actions/checkout from 3 to 42023.11.14
2023-11-13 dependabot... Bump fsfe/reuse-action from 1 to 2
2023-11-12 Sebastian Hoßupdate github actions (#52)2023.11.12
2023-11-12 Sebastian Hoßupdate parent to automanage error-prone annotations...
2023-11-08 Sebastian Hoßswitch to error-prone annotations to replace LGPL depen...
2023-11-05 sebhossUpdate parent to latest version2023.11.7
2023-10-05 sebhossUpdate parent to latest version2023.10.10
2023-09-05 sebhossUpdate parent to latest version
2023-08-05 sebhossUpdate parent to latest version2023.8.8
...
tags
4 months ago 2023.12.20
5 months ago 2023.12.5
5 months ago 2023.11.14
5 months ago 2023.11.12
6 months ago 2023.11.7
7 months ago 2023.10.10
9 months ago 2023.8.8
10 months ago 2023.7.11
11 months ago 2023.6.6
12 months ago 2023.5.9
13 months ago 2023.4.11
14 months ago 2023.3.7
15 months ago 2023.2.7
16 months ago 2023.1.10
16 months ago 2022.12.13
17 months ago 2022.12.6
...
heads
5 weeks ago update-parent
8 weeks ago main
16 months ago terraform