Storage units according to ISO IEC 80000-13:2008 implemented in Java.
- Immutable, type- and thread-safe object model for storage units
- Convenience factories to create units
- Basic arithmetic operators
- Comparisons and equality checks between units
- Lossless conversion between all units
- Human-readable text format, including custom formats
- Compatible with any
java.lang.Number - Custom serializers for Jackson, MongoDB, EclipseLink, and others
| Name | Symbol | Exponential | Absolute |
|---|---|---|---|
| Byte | B | 20 Byte | 1 Byte |
| Kibibyte | KiB | 210 Byte | 1 024 Byte |
| Mebibyte | MiB | 220 Byte | 1 048 576 Byte |
| Gibibyte | GiB | 230 Byte | 1 073 741 824 Byte |
| Tebibyte | TiB | 240 Byte | 1 099 511 627 776 Byte |
| Pebibyte | PiB | 250 Byte | 1 125 899 906 842 624 Byte |
| Exbibyte | EiB | 260 Byte | 1 152 921 504 606 846 976 Byte |
| Zebibyte | ZiB | 270 Byte | 1 180 591 620 717 411 303 424 Byte |
| Yobibyte | YiB | 280 Byte | 1 208 925 819 614 629 174 706 176 Byte |
| Robibyte | RiB | 290 Byte | 1 237 940 039 285 380 274 899 124 224 Byte |
| Qubibyte | QiB | 2100 Byte | 1 267 650 600 228 229 401 496 703 205 376 Byte |
| Name | Symbol | Exponential | Absolute |
|---|---|---|---|
| Byte | B | 100 Byte | 1 Byte |
| Kilobyte | KB | 103 Byte | 1 000 Byte |
| Megabyte | MB | 106 Byte | 1 000 000 Byte |
| Gigabyte | GB | 109 Byte | 1 000 000 000 Byte |
| Terabyte | TB | 1012 Byte | 1 000 000 000 000 Byte |
| Petabyte | PB | 1015 Byte | 1 000 000 000 000 000 Byte |
| Exabyte | EB | 1018 Byte | 1 000 000 000 000 000 000 Byte |
| Zettabyte | ZB | 1021 Byte | 1 000 000 000 000 000 000 000 Byte |
| Yottabyte | YB | 1024 Byte | 1 000 000 000 000 000 000 000 000 Byte |
| Ronnabyte | RB | 1027 Byte | 1 000 000 000 000 000 000 000 000 000 Byte |
| Quettabyte | QB | 1030 Byte | 1 000 000 000 000 000 000 000 000 000 000 Byte |
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' basedKilobyteunit = Kilobyte.valueOf(500) // 500 Byte or "0.50 kB"Kibibyteunit = Kibibyte.valueOf(512) // 512 Byte or "0.50 KiB"Megabyteunit = Megabyte.valueOf(1_000_000) // 1 000 000 Byte or "1.00 MB"Mebibyteunit = Mebibyte.valueOf(1_048_576) // 1 048 576 Byte or "1.00 MiB"// 'BigInteger' basedKilobyteunit = Kilobyte.valueOf(BigInteger.valueOf(500)) // 500 Byte or "0.50 kB"Kibibyteunit = Kibibyte.valueOf(BigInteger.valueOf(512)) // 512 Byte or "0.50 KiB"Megabyteunit = Megabyte.valueOf(BigInteger.valueOf(1000000)) // 1 000 000 Byte or "1.00 MB"Mebibyteunit = 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.
// 'long' basedStorageUnit<?> unit = StorageUnits.binaryValueOf(256) // Kibibyte (0.25 KiB)StorageUnit<?> unit = StorageUnits.binaryValueOf(1048576) // Mebibyte (1.00 MiB)// 'BigInteger' basedStorageUnit<?> unit = StorageUnits.binaryValueOf(BigInteger.valueOf(256)) // Kibibyte (0.25 MiB)StorageUnit<?> unit = StorageUnits.binaryValueOf(BigInteger.valueOf(1048576)) // Mebibyte (1.00 MiB)// 'long' basedStorageUnit<?> unit = StorageUnits.decimalValueOf(120000) // Kilobyte (120.00 kB)StorageUnit<?> unit = StorageUnits.decimalValueOf(1000000) // Megabyte (1.00 MB)// 'BigInteger' basedStorageUnit<?> 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.
importstaticwtf.metio.storageunits.model.StorageUnits.*;
Kibibyteunit = kibibyte(1) // 1 024 ByteMebibyteunit = mebibyte(1) // 1 048 576 ByteGibibyteunit = gibibyte(1) // 1 073 741 824 ByteTebibyteunit = tebibyte(1) // 1 099 511 627 776 BytePebibyteunit = pebibyte(1) // 1 125 899 906 842 624 ByteExbibyteunit = exbibyte(1) // 1 152 921 504 606 846 976 ByteZebibyteunit = zebibyte(1) // 1 180 591 620 717 411 303 424 ByteYobibyteunit = yobibyte(1) // 1 208 925 819 614 629 174 706 176 ByteRobibyteunit = robibyte(1) // 1 237 940 039 285 380 274 899 124 224 ByteQubibyteunit = qubibyte(1) // 1 267 650 600 228 229 401 496 703 205 376 ByteKilobyteunit = kilobyte(1) // 1 000 ByteMegabyteunit = megabyte(1) // 1 000 000 ByteGigabyteunit = gigabyte(1) // 1 000 000 000 ByteTerabyteunit = terabyte(1) // 1 000 000 000 000 BytePetabyteunit = petabyte(1) // 1 000 000 000 000 000 ByteExabyteunit = exabyte(1) // 1 000 000 000 000 000 000 ByteZettabyteunit = zettabyte(1) // 1 000 000 000 000 000 000 000 ByteYottabyteunit = yottabyte(1) // 1 000 000 000 000 000 000 000 000 ByteRonnabyteunit = ronnabyte(1) // 1 000 000 000 000 000 000 000 000 000 ByteQuettabyteunit = quettabyte(1) // 1 000 000 000 000 000 000 000 000 000 000 ByteEach unit implements the basic four math operations. All operations retain their original type, e.g. [Kilobyte] + [Megabyte] = [Kilobyte]
importstaticwtf.metio.storageunits.model.StorageUnits.*;
kilobyte(4).add(kilobyte(8)) // 4 Kilobyte + 8 Kilobyte = 12 Kilobyte = 12 000 Bytekibibyte(1).add(1024) // 1 Kibibyte + 1 024 Byte = 2 Kibibyte = 2 048 Bytekibibyte(1).subtract(24) // 1 024 Byte - 24 Byte = 1 000 Bytemegabyte(5).subtract(kilobyte(500)) // 5 Megabyte - 500 Kilobyte = 4.5 Megabyte = 4 500 Kilobyte = 4 500 000 Bytegigabyte(1).multiply(5) // 1 Gigabyte times 5 = 5 Gigabyteterabyte(1).divide(5) // 1 Terabyte divided by 5 = 0.2 Terabyte = 200 GigabyteEach unit is comparable to each other unit.
importstaticwtf.metio.storageunits.model.StorageUnits.*;
kibibyte(1024).compareTo(mebibyte(1)) == 0// truekibibyte(1000).compareTo(mebibyte(1)) == 0// falsepetabyte(3).compareTo(terabyte(3000)) == 0// truemegabyte(1000).equals(gigabyte(1)) // truemegabyte(1024).equals(gigabyte(1)) // falseterabyte(12).equals(gigabyte(12000)) // trueEach 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.
importstaticwtf.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 patternkilobyte(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 Localekilobyte(212345).toString("0.0", Locale.GERMAN) // "212345,0 kB"gibibyte(2123458).asTebibyte().toString("#,###.000", Locale.GERMAN) // "2.073,689 TiB"// use custom formatFormatcustomFormat = newDecimalFormat("#.00000");
terabyte(4).asTebibyte().toString(customFormat) // "3.63798 TiB"// without creating unit type firstlongnumberOfBytes = 1_000_000_000_000_000L;
formatAsPetabyte(numberOfBytes) // "1.00 PB"formatAsTerabyte(numberOfBytes) // "1000.00 TB"formatAsPebibyte(numberOfBytes) // "0.89 PiB"// use custom patternformatAsTerabyte(numberOfBytes, "#0.#####") // "1000 TB"formatAsPebibyte(numberOfBytes, "#0.#####") // "0.88818 PiB"// use custom pattern with specific LocaleformatAsTerabyte(numberOfBytes, "#0.#####", Locale.GERMAN) // "1000 TB"formatAsPebibyte(numberOfBytes, "#0.#####", Locale.GERMAN) // "0,88818 PiB"// use custom formatformatAsTerabyte(numberOfBytes, customFormat) // "1000.00000 TB"formatAsPebibyte(numberOfBytes, customFormat) // ".88818 PiB"Each unit can be converted to each other unit without loss of information.
importstaticwtf.metio.storageunits.model.StorageUnits.*;
Megabyteunit = kilobyte(1000).asMegabyte() // "1.00 MB"Kilobyteunit = gigabyte(12).asKilobyte() // "12000000.00 kB"Gigabyteunit = terabyte(1).asGigabyte() // "1000.00 GB"// convert to best-matchkilobyte(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)
importstaticwtf.metio.storageunits.model.StorageUnits.*;
BigDecimalkilobytes = megabyte(1).inKilobyte() // 1 000BigIntegerbytes = kibibyte(2).inByte() // 2 048BigDecimalterabytes = gigabyte(15).inTerabyte() // 0.015Multiple custom serializers, converters, and mappers are available for all storage units.
Use a Dozer converter like this:
importstaticwtf.metio.storageunits.dozer.*;
DozerBeanMapperBuilder.create()
.withCustomConverter(newBigIntegerBinaryStorageUnitConverter())
.withCustomConverter(newBigIntegerDecimalStorageUnitConverter())
.withCustomConverter(newLongBinaryStorageUnitConverter())
.withCustomConverter(newLongDecimalStorageUnitConverter())
.build();Use any of the three converters like this:
importstaticwtf.metio.storageunits.eclipselink.*;
@EntitypublicclassHardDiskimplementsSerializable {
@Basic@Converter (
name="binaryConverter",
converterClass=BinaryStorageUnitConverter.class
)
@Convert("binaryConverter")
publicStorageUnit<?> getFreeSize() {
returnfreeSize;
}
@Basic@Converter (
name="decimalConverter",
converterClass=DecimalyStorageUnitConverter.class
)
@Convert("decimalConverter")
publicStorageUnit<?> getTotalSize() {
returntotalSize;
}
}Use a GSON serializer/deserializer like this:
importstaticwtf.metio.storageunits.gson.*;
newGsonBuilder()
.registerTypeHierarchyAdapter(StorageUnit.class, newStorageUnitSerializer())
.registerTypeHierarchyAdapter(StorageUnit.class, newBinaryStorageUnitDeserializer())
.registerTypeHierarchyAdapter(StorageUnit.class, newDecimalStorageUnitDeserializer())
.create();Use the provided StorageUnitModule like this:
importstaticwtf.metio.storageunits.jackson.*;
ObjectMapperobjectMapper = newObjectMapper();
objectMapper.registerModule(newStorageUnitModule()); // defaults to binary unitsobjectMapper.registerModule(newStorageUnitModule(StorageUnitModule.PreferredUnitType.BINARY));
objectMapper.registerModule(newStorageUnitModule(StorageUnitModule.PreferredUnitType.DECIMAL));Use the provided AttributeConverters like this:
importstaticwtf.metio.storageunits.jakarta.*;
@EntitypublicclassHardDiskimplementsSerializable {
@Convert(converter = BinaryStorageUnitConverter.class)
publicStorageUnit<?> getFreeSize() {
returnfreeSize;
}
@Convert(converter = DecimalStorageUnitConverter.class)
publicStorageUnit<?> getTotalSize() {
returntotalSize;
}
}Use any of the available mappers like this:
importstaticwtf.metio.storageunits.mapstruct.*;
@Mapper( uses = BigIntegerToBinaryUnitMapper.class )
publicinterfaceMovieMapper {
DestinationTypetoDestination(SourceTypesourceValue);
}Use any of the available converters like this:
importstaticwtf.metio.storageunits.modelmapper.*;
modelMapper.addConverter(newBigIntegerToBinaryUnitConverter());
modelMapper.addConverter(newBigIntegerToDecimalUnitConverter());
modelMapper.addConverter(newLongToBinaryUnitConverter());
modelMapper.addConverter(newLongToDecimalUnitConverter());
modelMapper.addConverter(newStorageUnitToBigIntegerConverter());Use any of the three codecs like this:
importstaticwtf.metio.storageunits.mongodb.*;
CodecRegistrybinaryRegistry = CodecRegistries.fromCodecs(newBinaryStorageUnitCodec(), ...);
CodecRegistrydecimalRegistry = CodecRegistries.fromCodecs(newDecimalStorageUnitCodec(), ...);Use any of the provided converters like this:
importstaticwtf.metio.storageunits.orika.*;
ConverterFactoryconverterFactory = mapperFactory.getConverterFactory();
converterFactory.registerConverter(newBinaryStorageUnitConverter());
converterFactory.registerConverter(newDecimalStorageUnitConverter());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.
Originally inspired by Twitters util package.