add some tests
[storage-units.git] / README.md
blob4d8a55877023f9de71a84c6775cebd94f5da7b06
1 <!--
2 SPDX-FileCopyrightText: The Storage-Units Authors
3 SPDX-License-Identifier: 0BSD
4  -->
6 # Storage-Units
8 Storage units according to ISO IEC 80000-13:2008 implemented in Java.
10 ## Features
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
21 ### Available Units
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 |
35 | Name      | Symbol | Exponential          | Absolute                               |
36 |-----------|--------|----------------------|----------------------------------------|
37 | Byte      | B      | 10<sup>0</sup> Byte  | 1 Byte                                 |
38 | Kilobyte  | KB     | 10<sup>3</sup> Byte  | 1 000 Byte                             |
39 | Megabyte  | MB     | 10<sup>6</sup> Byte  | 1 000 000 Byte                         |
40 | Gigabyte  | GB     | 10<sup>9</sup> Byte  | 1 000 000 000 Byte                     |
41 | Terabyte  | TB     | 10<sup>12</sup> Byte | 1 000 000 000 000 Byte                 |
42 | Petabyte  | PB     | 10<sup>15</sup> Byte | 1 000 000 000 000 000 Byte             |
43 | Exabyte   | EB     | 10<sup>18</sup> Byte | 1 000 000 000 000 000 000 Byte         |
44 | Zettabyte | ZB     | 10<sup>21</sup> Byte | 1 000 000 000 000 000 000 000 Byte     |
45 | Yottabyte | YB     | 10<sup>24</sup> Byte | 1 000 000 000 000 000 000 000 000 Byte |
47 ## Usage
49 ### Factories
51 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`.
53 ```java
54 // 'long' based
55 Kilobyte unit = Kilobyte.valueOf(500)                                       // 500 Byte or "0.50 kB"
56 Kibibyte unit = Kibibyte.valueOf(512)                                       // 512 Byte or "0.50 KiB"
58 Megabyte unit = Megabyte.valueOf(1_000_000)                                 // 1 000 000 Byte or "1.00 MB"
59 Mebibyte unit = Mebibyte.valueOf(1_048_576)                                 // 1 048 576 Byte or "1.00 MiB"
61 // 'BigInteger' based
62 Kilobyte unit = Kilobyte.valueOf(BigInteger.valueOf(500))                   // 500 Byte or "0.50 kB"
63 Kibibyte unit = Kibibyte.valueOf(BigInteger.valueOf(512))                   // 512 Byte or "0.50 KiB"
65 Megabyte unit = Megabyte.valueOf(BigInteger.valueOf(1000000))               // 1 000 000 Byte or "1.00 MB"
66 Mebibyte unit = Mebibyte.valueOf(BigInteger.valueOf(1_048_576))             // 1 048 576 Byte or "1.00 MB"
67 ```
69 The `StorageUnits` class offers three factory methods that automatically pick the best-matching unit for a given number of bytes.
71 #### Binary Units
73 ```java
74 // 'long' based
75 StorageUnit<?> unit = StorageUnits.binaryValueOf(256)                         // Kibibyte (0.25 KiB)
76 StorageUnit<?> unit = StorageUnits.binaryValueOf(1048576)                     // Mebibyte (1.00 MiB)
78 // 'BigInteger' based
79 StorageUnit<?> unit = StorageUnits.binaryValueOf(BigInteger.valueOf(256))     // Kibibyte (0.25 MiB)
80 StorageUnit<?> unit = StorageUnits.binaryValueOf(BigInteger.valueOf(1048576)) // Mebibyte (1.00 MiB)
81 ```
83 #### Decimal Units
85 ```java
86 // 'long' based
87 StorageUnit<?> unit = StorageUnits.decimalValueOf(120000)                      // Kilobyte (120.00 kB)
88 StorageUnit<?> unit = StorageUnits.decimalValueOf(1000000)                     // Megabyte (1.00 MB)
90 // 'BigInteger' based
91 StorageUnit<?> unit = StorageUnits.decimalValueOf(BigInteger.valueOf(120000))  // Kilobyte (120.00 kB)
92 StorageUnit<?> unit = StorageUnits.decimalValueOf(BigInteger.valueOf(1000000)) // Megabyte (1.00 MB)
93 ```
95 Additionally high-level factory methods are also available in the `StorageUnits` class.
97 ```java
98 import static wtf.metio.storageunits.model.StorageUnits.*;
100 Kibibyte unit = kibibyte(1)   // 1 024 Byte
101 Mebibyte unit = mebibyte(1)   // 1 048 576 Byte
102 Gibibyte unit = gibibyte(1)   // 1 073 741 824 Byte
103 Tebibyte unit = tebibyte(1)   // 1 099 511 627 776 Byte
104 Pebibyte unit = pebibyte(1)   // 1 125 899 906 842 624 Byte
105 Exbibyte unit = exbibyte(1)   // 1 152 921 504 606 846 976 Byte
106 Zebibyte unit = zebibyte(1)   // 1 180 591 620 717 411 303 424 Byte
107 Yobibyte unit = yobibyte(1)   // 1 208 925 819 614 629 174 706 176 Byte
109 Kilobyte unit = kilobyte(1)   // 1 000 Byte
110 Megabyte unit = megabyte(1)   // 1 000 000 Byte
111 Gigabyte unit = gigabyte(1)   // 1 000 000 000 Byte
112 Terabyte unit = terabyte(1)   // 1 000 000 000 000 Byte
113 Petabyte unit = petabyte(1)   // 1 000 000 000 000 000 Byte
114 Exabyte unit = exabyte(1)     // 1 000 000 000 000 000 000 Byte
115 Zettabyte unit = zettabyte(1) // 1 000 000 000 000 000 000 000 Byte
116 Yottabyte unit = yottabyte(1) // 1 000 000 000 000 000 000 000 000 Byte
119 ### Add, Subtract, Multiply, Divide
121 Each unit implements the basic four math operations. All operations retain their original type, e.g. `[Kilobyte] + [Megabyte] = [Kilobyte]`
123 ```java
124 import static wtf.metio.storageunits.model.StorageUnits.*;
126 kilobyte(4).add(kilobyte(8))        // 4 Kilobyte + 8 Kilobyte = 12 Kilobyte = 12 000 Byte
127 kibibyte(1).add(1024)               // 1 Kibibyte + 1 024 Byte = 2 Kibibyte = 2 048 Byte
128 kibibyte(1).subtract(24)            // 1 024 Byte - 24 Byte = 1 000 Byte
129 megabyte(5).subtract(kilobyte(500)) // 5 Megabyte - 500 Kilobyte = 4.5 Megabyte = 4 500 Kilobyte = 4 500 000 Byte
130 gigabyte(1).multiply(5)             // 1 Gigabyte times 5 = 5 Gigabyte
131 terabyte(1).divide(5)               // 1 Terabyte divided by 5 = 0.2 Terabyte = 200 Gigabyte
134 ### Comparison & Equality
136 Each unit is comparable to each other unit.
138 ```java
139 import static wtf.metio.storageunits.model.StorageUnits.*;
141 kibibyte(1024).compareTo(mebibyte(1)) == 0 // true
142 kibibyte(1000).compareTo(mebibyte(1)) == 0 // false
143 petabyte(3).compareTo(terabyte(3000)) == 0 // true
145 megabyte(1000).equals(gigabyte(1))         // true
146 megabyte(1024).equals(gigabyte(1))         // false
147 terabyte(12).equals(gigabyte(12000))       // true
150 ### Formatting
152 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.
154 ```java
155 import static wtf.metio.storageunits.model.StorageUnits.*;
157 // default pattern '0.00'
158 terabyte(2).toString()                         // "2.00 TB"
159 gigabyte(1).add(megabyte(200)).toString()      // "1.20 GB"
160 petabyte(1).subtract(terabyte(250)).toString() // "0.75 PB"
162 // use custom pattern
163 kilobyte(212345).toString("0.0")                                    // "212345.0 kB"
164 gibibyte(2123458).asTebibyte().toString("#,###.000")                // "2,073.689 TiB"
165 kilobyte(120).asMegabyte().add(gigabyte(1)).toString("#,##0.00000") // "1,000.12000 MB"
167 // use custom pattern with specific Locale
168 kilobyte(212345).toString("0.0", Locale.GERMAN)                     // "212345,0 kB"
169 gibibyte(2123458).asTebibyte().toString("#,###.000", Locale.GERMAN) // "2.073,689 TiB"
171 // use custom format
172 Format customFormat = new DecimalFormat("#.00000");
173 terabyte(4).asTebibyte().toString(customFormat) // "3.63798 TiB"
175 // without creating unit type first
176 long numberOfBytes = 1_000_000_000_000_000L;
177 formatAsPetabyte(numberOfBytes) // "1.00 PB"
178 formatAsTerabyte(numberOfBytes) // "1000.00 TB"
179 formatAsPebibyte(numberOfBytes) // "0.89 PiB"
181 // use custom pattern
182 formatAsTerabyte(numberOfBytes, "#0.#####") // "1000 TB"
183 formatAsPebibyte(numberOfBytes, "#0.#####") // "0.88818 PiB"
185 // use custom pattern with specific Locale
186 formatAsTerabyte(numberOfBytes, "#0.#####", Locale.GERMAN) // "1000 TB"
187 formatAsPebibyte(numberOfBytes, "#0.#####", Locale.GERMAN) // "0,88818 PiB"
189 // use custom format
190 formatAsTerabyte(numberOfBytes, customFormat) // "1000.00000 TB"
191 formatAsPebibyte(numberOfBytes, customFormat) // ".88818 PiB"
194 ### Conversions
196 Each unit can be converted to each other unit without loss of information.
198 ```java
199 import static wtf.metio.storageunits.model.StorageUnits.*;
201 Megabyte unit = kilobyte(1000).asMegabyte() // "1.00 MB"
202 Kilobyte unit = gigabyte(12).asKilobyte()   // "12000000.00 kB"
203 Gigabyte unit = terabyte(1).asGigabyte()    // "1000.00 GB"
205 // convert to best-match
206 kilobyte(1100).asBestMatchingUnit()          // "1.10 MB"
207 kilobyte(1100).asBestMatchingBinaryUnit()    // "1.05 MiB"
208 kilobyte(1100).asBestMatchingDecimalUnit()   // "1.10 MB"
209 kilobyte(1100).asBestMatchingCommonUnit()    // "1.05 MB"
212 Each unit can be expressed as a fraction of another unit (precise up to 24 decimal places)
214 ```java
215 import static wtf.metio.storageunits.model.StorageUnits.*;
217 BigDecimal kilobytes = megabyte(1).inKilobyte()  // 1 000
218 BigInteger bytes = kibibyte(2).inByte()          // 2 048
219 BigDecimal terabytes = gigabyte(15).inTerabyte() // 0.015
222 ### Serialization
224 Multiple custom serializers are available to store storage units.
226 #### EclipseLink
228 Use any of the three converters like this:
230 ```java
231 @Entity
232 public class HardDisk implements Serializable {
234     @Basic
235     @Converter (
236         name="binaryConverter",
237         converterClass=wtf.metio.storageunits.eclipselink.BinaryStorageUnitConverter.class
238     )
239     @Convert("binaryConverter")
240     public StorageUnit<?> getFreeSize() {
241         return freeSize;
242     }
244     @Basic
245     @Converter (
246         name="decimalConverter",
247         converterClass=wtf.metio.storageunits.eclipselink.DecimalyStorageUnitConverter.class
248     )
249     @Convert("decimalConverter")
250     public StorageUnit<?> getTotalSize() {
251         return totalSize;
252     }
257 #### MongoDB
259 Use any of the three codecs like this:
261 ```java
262 CodecRegistry binaryRegistry = CodecRegistries.fromCodecs(new BinaryStorageUnitCodec(), ...);
263 CodecRegistry decimalRegistry = CodecRegistries.fromCodecs(new DecimalStorageUnitCodec(), ...);
266 #### Jackson
268 Use the provided `StorageUnitModule` like this:
270 ```java
271 ObjectMapper objectMapper = new ObjectMapper();
272 objectMapper.registerModule(new StorageUnitModule()); // defaults to binary units
273 objectMapper.registerModule(new StorageUnitModule(StorageUnitModule.PreferredUnitType.BINARY));
274 objectMapper.registerModule(new StorageUnitModule(StorageUnitModule.PreferredUnitType.DECIMAL));
277 ### Integration
279 To use this project just declare the following dependency inside your POM:
281 ```xml
282 <dependencies>
283   <dependency>
284     <groupId>wtf.metio.storage-units</groupId>
285     <artifactId>storage-units-model</artifactId>
286     <version>${version.storage-units}</version>
287   </dependency>
289   <!-- EclipseLink ONLY -->
290   <dependency>
291     <groupId>wtf.metio.storage-units</groupId>
292     <artifactId>storage-units-eclipselink</artifactId>
293     <version>${version.storage-units}</version>
294   </dependency>
295   <!-- EclipseLink ONLY -->
297   <!-- MongoDB ONLY -->
298   <dependency>
299     <groupId>wtf.metio.storage-units</groupId>
300     <artifactId>storage-units-mongodb</artifactId>
301     <version>${version.storage-units}</version>
302   </dependency>
303   <!-- MongoDB ONLY -->
305   <!-- Jackson ONLY -->
306   <dependency>
307     <groupId>wtf.metio.storage-units</groupId>
308     <artifactId>storage-units-jackson</artifactId>
309     <version>${version.storage-units}</version>
310   </dependency>
311   <!-- Jackson ONLY -->
312 </dependencies>
315 Replace `${version.storage-units}` with the [latest release](https://search.maven.org/search?q=g:wtf.metio.storageunits).
317 ## Reference
319 Originally inspired by [Twitters util](https://github.com/twitter/util#space) package.
321 ## Alternatives
323 * [Byte Units](https://github.com/JakeWharton/byteunits)
324 * [triava](https://github.com/trivago/triava)
326 ## License
329 Permission to use, copy, modify, and/or distribute this software for any
330 purpose with or without fee is hereby granted.
332 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
333 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
334 FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
335 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
336 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
337 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
338 PERFORMANCE OF THIS SOFTWARE.