2 SPDX-FileCopyrightText: The Storage-Units Authors
3 SPDX-License-Identifier: 0BSD
8 Storage units according to ISO IEC 80000-13:2008 implemented in Java.
12 * Immutable, type- and thread-safe object model for storage units
13 * Convenience factories to create units
14 * Basic arithmetic operators
15 * Comparisons and equality checks between units
16 * Lossless conversion between all units
17 * Human-readable text format, including custom formats
18 * Compatible with any `java.lang.Number`
19 * Custom serializers for Jackson, MongoDB, EclipseLink, and others
23 | Name | Symbol | Exponential | Absolute |
24 |----------|--------|----------------------|------------------------------------------------|
25 | Byte | B | 2<sup>0</sup> Byte | 1 Byte |
26 | Kibibyte | KiB | 2<sup>10</sup> Byte | 1 024 Byte |
27 | Mebibyte | MiB | 2<sup>20</sup> Byte | 1 048 576 Byte |
28 | Gibibyte | GiB | 2<sup>30</sup> Byte | 1 073 741 824 Byte |
29 | Tebibyte | TiB | 2<sup>40</sup> Byte | 1 099 511 627 776 Byte |
30 | Pebibyte | PiB | 2<sup>50</sup> Byte | 1 125 899 906 842 624 Byte |
31 | Exbibyte | EiB | 2<sup>60</sup> Byte | 1 152 921 504 606 846 976 Byte |
32 | Zebibyte | ZiB | 2<sup>70</sup> Byte | 1 180 591 620 717 411 303 424 Byte |
33 | Yobibyte | YiB | 2<sup>80</sup> Byte | 1 208 925 819 614 629 174 706 176 Byte |
34 | Robibyte | RiB | 2<sup>90</sup> Byte | 1 237 940 039 285 380 274 899 124 224 Byte |
35 | Qubibyte | QiB | 2<sup>100</sup> Byte | 1 267 650 600 228 229 401 496 703 205 376 Byte |
37 | Name | Symbol | Exponential | Absolute |
38 |------------|--------|----------------------|------------------------------------------------|
39 | Byte | B | 10<sup>0</sup> Byte | 1 Byte |
40 | Kilobyte | KB | 10<sup>3</sup> Byte | 1 000 Byte |
41 | Megabyte | MB | 10<sup>6</sup> Byte | 1 000 000 Byte |
42 | Gigabyte | GB | 10<sup>9</sup> Byte | 1 000 000 000 Byte |
43 | Terabyte | TB | 10<sup>12</sup> Byte | 1 000 000 000 000 Byte |
44 | Petabyte | PB | 10<sup>15</sup> Byte | 1 000 000 000 000 000 Byte |
45 | Exabyte | EB | 10<sup>18</sup> Byte | 1 000 000 000 000 000 000 Byte |
46 | Zettabyte | ZB | 10<sup>21</sup> Byte | 1 000 000 000 000 000 000 000 Byte |
47 | Yottabyte | YB | 10<sup>24</sup> Byte | 1 000 000 000 000 000 000 000 000 Byte |
48 | Ronnabyte | RB | 10<sup>27</sup> Byte | 1 000 000 000 000 000 000 000 000 000 Byte |
49 | Quettabyte | QB | 10<sup>30</sup> Byte | 1 000 000 000 000 000 000 000 000 000 000 Byte |
55 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`.
59 Kilobyte unit = Kilobyte.valueOf(500) // 500 Byte or "0.50 kB"
60 Kibibyte unit = Kibibyte.valueOf(512) // 512 Byte or "0.50 KiB"
62 Megabyte unit = Megabyte.valueOf(1_000_000) // 1 000 000 Byte or "1.00 MB"
63 Mebibyte unit = Mebibyte.valueOf(1_048_576) // 1 048 576 Byte or "1.00 MiB"
66 Kilobyte unit = Kilobyte.valueOf(BigInteger.valueOf(500)) // 500 Byte or "0.50 kB"
67 Kibibyte unit = Kibibyte.valueOf(BigInteger.valueOf(512)) // 512 Byte or "0.50 KiB"
69 Megabyte unit = Megabyte.valueOf(BigInteger.valueOf(1000000)) // 1 000 000 Byte or "1.00 MB"
70 Mebibyte unit = Mebibyte.valueOf(BigInteger.valueOf(1_048_576)) // 1 048 576 Byte or "1.00 MB"
73 The `StorageUnits` class offers three factory methods that automatically pick the best-matching unit for a given number of bytes.
79 StorageUnit<?> unit = StorageUnits.binaryValueOf(256) // Kibibyte (0.25 KiB)
80 StorageUnit<?> unit = StorageUnits.binaryValueOf(1048576) // Mebibyte (1.00 MiB)
83 StorageUnit<?> unit = StorageUnits.binaryValueOf(BigInteger.valueOf(256)) // Kibibyte (0.25 MiB)
84 StorageUnit<?> unit = StorageUnits.binaryValueOf(BigInteger.valueOf(1048576)) // Mebibyte (1.00 MiB)
91 StorageUnit<?> unit = StorageUnits.decimalValueOf(120000) // Kilobyte (120.00 kB)
92 StorageUnit<?> unit = StorageUnits.decimalValueOf(1000000) // Megabyte (1.00 MB)
95 StorageUnit<?> unit = StorageUnits.decimalValueOf(BigInteger.valueOf(120000)) // Kilobyte (120.00 kB)
96 StorageUnit<?> unit = StorageUnits.decimalValueOf(BigInteger.valueOf(1000000)) // Megabyte (1.00 MB)
99 Additionally high-level factory methods are also available in the `StorageUnits` class.
102 import static wtf.metio.storageunits.model.StorageUnits.*;
104 Kibibyte unit = kibibyte(1) // 1 024 Byte
105 Mebibyte unit = mebibyte(1) // 1 048 576 Byte
106 Gibibyte unit = gibibyte(1) // 1 073 741 824 Byte
107 Tebibyte unit = tebibyte(1) // 1 099 511 627 776 Byte
108 Pebibyte unit = pebibyte(1) // 1 125 899 906 842 624 Byte
109 Exbibyte unit = exbibyte(1) // 1 152 921 504 606 846 976 Byte
110 Zebibyte unit = zebibyte(1) // 1 180 591 620 717 411 303 424 Byte
111 Yobibyte unit = yobibyte(1) // 1 208 925 819 614 629 174 706 176 Byte
112 Robibyte unit = robibyte(1) // 1 237 940 039 285 380 274 899 124 224 Byte
113 Qubibyte unit = qubibyte(1) // 1 267 650 600 228 229 401 496 703 205 376 Byte
115 Kilobyte unit = kilobyte(1) // 1 000 Byte
116 Megabyte unit = megabyte(1) // 1 000 000 Byte
117 Gigabyte unit = gigabyte(1) // 1 000 000 000 Byte
118 Terabyte unit = terabyte(1) // 1 000 000 000 000 Byte
119 Petabyte unit = petabyte(1) // 1 000 000 000 000 000 Byte
120 Exabyte unit = exabyte(1) // 1 000 000 000 000 000 000 Byte
121 Zettabyte unit = zettabyte(1) // 1 000 000 000 000 000 000 000 Byte
122 Yottabyte unit = yottabyte(1) // 1 000 000 000 000 000 000 000 000 Byte
123 Ronnabyte unit = ronnabyte(1) // 1 000 000 000 000 000 000 000 000 000 Byte
124 Quettabyte unit = quettabyte(1) // 1 000 000 000 000 000 000 000 000 000 000 Byte
127 ### Add, Subtract, Multiply, Divide
129 Each unit implements the basic four math operations. All operations retain their original type, e.g. `[Kilobyte] + [Megabyte] = [Kilobyte]`
132 import static wtf.metio.storageunits.model.StorageUnits.*;
134 kilobyte(4).add(kilobyte(8)) // 4 Kilobyte + 8 Kilobyte = 12 Kilobyte = 12 000 Byte
135 kibibyte(1).add(1024) // 1 Kibibyte + 1 024 Byte = 2 Kibibyte = 2 048 Byte
136 kibibyte(1).subtract(24) // 1 024 Byte - 24 Byte = 1 000 Byte
137 megabyte(5).subtract(kilobyte(500)) // 5 Megabyte - 500 Kilobyte = 4.5 Megabyte = 4 500 Kilobyte = 4 500 000 Byte
138 gigabyte(1).multiply(5) // 1 Gigabyte times 5 = 5 Gigabyte
139 terabyte(1).divide(5) // 1 Terabyte divided by 5 = 0.2 Terabyte = 200 Gigabyte
142 ### Comparison & Equality
144 Each unit is comparable to each other unit.
147 import static wtf.metio.storageunits.model.StorageUnits.*;
149 kibibyte(1024).compareTo(mebibyte(1)) == 0 // true
150 kibibyte(1000).compareTo(mebibyte(1)) == 0 // false
151 petabyte(3).compareTo(terabyte(3000)) == 0 // true
153 megabyte(1000).equals(gigabyte(1)) // true
154 megabyte(1024).equals(gigabyte(1)) // false
155 terabyte(12).equals(gigabyte(12000)) // true
160 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.
163 import static wtf.metio.storageunits.model.StorageUnits.*;
165 // default pattern '0.00'
166 terabyte(2).toString() // "2.00 TB"
167 gigabyte(1).add(megabyte(200)).toString() // "1.20 GB"
168 petabyte(1).subtract(terabyte(250)).toString() // "0.75 PB"
170 // use custom pattern
171 kilobyte(212345).toString("0.0") // "212345.0 kB"
172 gibibyte(2123458).asTebibyte().toString("#,###.000") // "2,073.689 TiB"
173 kilobyte(120).asMegabyte().add(gigabyte(1)).toString("#,##0.00000") // "1,000.12000 MB"
175 // use custom pattern with specific Locale
176 kilobyte(212345).toString("0.0", Locale.GERMAN) // "212345,0 kB"
177 gibibyte(2123458).asTebibyte().toString("#,###.000", Locale.GERMAN) // "2.073,689 TiB"
180 Format customFormat = new DecimalFormat("#.00000");
181 terabyte(4).asTebibyte().toString(customFormat) // "3.63798 TiB"
183 // without creating unit type first
184 long numberOfBytes = 1_000_000_000_000_000L;
185 formatAsPetabyte(numberOfBytes) // "1.00 PB"
186 formatAsTerabyte(numberOfBytes) // "1000.00 TB"
187 formatAsPebibyte(numberOfBytes) // "0.89 PiB"
189 // use custom pattern
190 formatAsTerabyte(numberOfBytes, "#0.#####") // "1000 TB"
191 formatAsPebibyte(numberOfBytes, "#0.#####") // "0.88818 PiB"
193 // use custom pattern with specific Locale
194 formatAsTerabyte(numberOfBytes, "#0.#####", Locale.GERMAN) // "1000 TB"
195 formatAsPebibyte(numberOfBytes, "#0.#####", Locale.GERMAN) // "0,88818 PiB"
198 formatAsTerabyte(numberOfBytes, customFormat) // "1000.00000 TB"
199 formatAsPebibyte(numberOfBytes, customFormat) // ".88818 PiB"
204 Each unit can be converted to each other unit without loss of information.
207 import static wtf.metio.storageunits.model.StorageUnits.*;
209 Megabyte unit = kilobyte(1000).asMegabyte() // "1.00 MB"
210 Kilobyte unit = gigabyte(12).asKilobyte() // "12000000.00 kB"
211 Gigabyte unit = terabyte(1).asGigabyte() // "1000.00 GB"
213 // convert to best-match
214 kilobyte(1100).asBestMatchingUnit() // "1.10 MB"
215 kilobyte(1100).asBestMatchingBinaryUnit() // "1.05 MiB"
216 kilobyte(1100).asBestMatchingDecimalUnit() // "1.10 MB"
219 Each unit can be expressed as a fraction of another unit (precise up to 24 decimal places)
222 import static wtf.metio.storageunits.model.StorageUnits.*;
224 BigDecimal kilobytes = megabyte(1).inKilobyte() // 1 000
225 BigInteger bytes = kibibyte(2).inByte() // 2 048
226 BigDecimal terabytes = gigabyte(15).inTerabyte() // 0.015
229 ### Serialization/Converters/Mappers
231 Multiple custom serializers, converters, and mappers are available for all storage units.
235 Use a [Dozer](https://dozermapper.github.io/) converter like this:
238 import static wtf.metio.storageunits.dozer.*;
240 DozerBeanMapperBuilder.create()
241 .withCustomConverter(new BigIntegerBinaryStorageUnitConverter())
242 .withCustomConverter(new BigIntegerDecimalStorageUnitConverter())
243 .withCustomConverter(new LongBinaryStorageUnitConverter())
244 .withCustomConverter(new LongDecimalStorageUnitConverter())
250 Use any of the three converters like this:
253 import static wtf.metio.storageunits.eclipselink.*;
256 public class HardDisk implements Serializable {
260 name="binaryConverter",
261 converterClass=BinaryStorageUnitConverter.class
263 @Convert("binaryConverter")
264 public StorageUnit<?> getFreeSize() {
270 name="decimalConverter",
271 converterClass=DecimalyStorageUnitConverter.class
273 @Convert("decimalConverter")
274 public StorageUnit<?> getTotalSize() {
283 Use the provided `StorageUnitModule` like this:
286 import static wtf.metio.storageunits.jackson.*;
288 ObjectMapper objectMapper = new ObjectMapper();
289 objectMapper.registerModule(new StorageUnitModule()); // defaults to binary units
290 objectMapper.registerModule(new StorageUnitModule(StorageUnitModule.PreferredUnitType.BINARY));
291 objectMapper.registerModule(new StorageUnitModule(StorageUnitModule.PreferredUnitType.DECIMAL));
296 Use the provided `AttributeConverter`s like this:
299 import static wtf.metio.storageunits.jakarta.*;
302 public class HardDisk implements Serializable {
304 @Convert(converter = BinaryStorageUnitConverter.class)
305 public StorageUnit<?> getFreeSize() {
309 @Convert(converter = DecimalStorageUnitConverter.class)
310 public StorageUnit<?> getTotalSize() {
319 Use any of the available mappers like this:
322 import static wtf.metio.storageunits.mapstruct.*;
324 @Mapper( uses = BigIntegerToBinaryUnitMapper.class )
325 public interface MovieMapper {
327 DestinationType toDestination(SourceType sourceValue);
334 Use any of the available converters like this:
337 import static wtf.metio.storageunits.modelmapper.*;
339 modelMapper.addConverter(new BigIntegerToBinaryUnitConverter());
340 modelMapper.addConverter(new BigIntegerToDecimalUnitConverter());
341 modelMapper.addConverter(new LongToBinaryUnitConverter());
342 modelMapper.addConverter(new LongToDecimalUnitConverter());
343 modelMapper.addConverter(new StorageUnitToBigIntegerConverter());
348 Use any of the three codecs like this:
351 import static wtf.metio.storageunits.mongodb.*;
353 CodecRegistry binaryRegistry = CodecRegistries.fromCodecs(new BinaryStorageUnitCodec(), ...);
354 CodecRegistry decimalRegistry = CodecRegistries.fromCodecs(new DecimalStorageUnitCodec(), ...);
359 Use any of the provided converters like this:
362 import static wtf.metio.storageunits.orika.*;
364 ConverterFactory converterFactory = mapperFactory.getConverterFactory();
365 converterFactory.registerConverter(new BinaryStorageUnitConverter());
366 converterFactory.registerConverter(new DecimalStorageUnitConverter());
371 To use this project just declare the following dependency inside your POM:
376 <groupId>wtf.metio.storage-units</groupId>
377 <artifactId>storage-units-model</artifactId>
378 <version>${version.storage-units}</version>
383 <groupId>wtf.metio.storage-units</groupId>
384 <artifactId>storage-units-dozer</artifactId>
385 <version>${version.storage-units}</version>
389 <!-- EclipseLink ONLY -->
391 <groupId>wtf.metio.storage-units</groupId>
392 <artifactId>storage-units-eclipselink</artifactId>
393 <version>${version.storage-units}</version>
395 <!-- EclipseLink ONLY -->
397 <!-- Jackson ONLY -->
399 <groupId>wtf.metio.storage-units</groupId>
400 <artifactId>storage-units-jackson</artifactId>
401 <version>${version.storage-units}</version>
403 <!-- Jackson ONLY -->
405 <!-- Jakarta ONLY -->
407 <groupId>wtf.metio.storage-units</groupId>
408 <artifactId>storage-units-jakarta</artifactId>
409 <version>${version.storage-units}</version>
411 <!-- Jakarta ONLY -->
413 <!-- MapStruct ONLY -->
415 <groupId>wtf.metio.storage-units</groupId>
416 <artifactId>storage-units-mapstruct</artifactId>
417 <version>${version.storage-units}</version>
419 <!-- MapStruct ONLY -->
421 <!-- ModelMapper ONLY -->
423 <groupId>wtf.metio.storage-units</groupId>
424 <artifactId>storage-units-modelmapper</artifactId>
425 <version>${version.storage-units}</version>
427 <!-- ModelMapper ONLY -->
429 <!-- MongoDB ONLY -->
431 <groupId>wtf.metio.storage-units</groupId>
432 <artifactId>storage-units-mongodb</artifactId>
433 <version>${version.storage-units}</version>
435 <!-- MongoDB ONLY -->
439 <groupId>wtf.metio.storage-units</groupId>
440 <artifactId>storage-units-orika</artifactId>
441 <version>${version.storage-units}</version>
447 Replace `${version.storage-units}` with the [latest release](https://search.maven.org/search?q=g:wtf.metio.storage-units).
451 Originally inspired by [Twitters util](https://github.com/twitter/util#space) package.
455 * [Byte Units](https://github.com/JakeWharton/byteunits)
456 * [triava](https://github.com/trivago/triava)
461 Permission to use, copy, modify, and/or distribute this software for any
462 purpose with or without fee is hereby granted.
464 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
465 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
466 FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
467 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
468 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
469 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
470 PERFORMANCE OF THIS SOFTWARE.