You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
Sebastian Hoß 7e7636b2f8 remove name extension for parent 3 years ago
AUTHORS permissions + nullable annotations 4 years ago
build/docker update docker build env 4 years ago
storage-units update test case w/ actual answer 4 years ago
storage-units-eclipselink fix #6 4 years ago
storage-units-jackson remove unnecessary JsonProcessingException 4 years ago
storage-units-mongodb fix #11 4 years ago
.gitignore ignore ansible markers 3 years ago
.travis.yml update travis config to latest & greatest 4 years ago
CHANGELOG.asciidoc update changelog 4 years ago
CODE_OF_CONDUCT.asciidoc md -> asciidoc 4 years ago
CONTRIBUTING.asciidoc update contributor guide 4 years ago
LICENSE switch to cc0 4 years ago
Makefile fix update-maintenance-badge goal 3 years ago
README.asciidoc Update maintenance badge 3 years ago
maven-version-rules.xml add version rules file 4 years ago
pom.xml remove name extension for parent 3 years ago

README.asciidoc

= Storage-Units image:https://img.shields.io/badge/email-%40metio-brightgreen.svg?style=social&label=mail["Discuss on Google Groups", link="https://groups.google.com/forum/#!forum/metio"] image:https://img.shields.io/badge/irc-%23metio.wtf-brightgreen.svg?style=social&label=IRC["Chat on IRC", link="http://webchat.freenode.net/?channels=metio.wtf"]
Sebastian Hoß <http://seb.xn--ho-hia.de/[@sebhoss]>
:github-org: sebhoss
:project-name: storage-units
:project-group: de.xn--ho-hia.storage_units
:coverity-project: 2658
:codacy-project: d3cfbbc415c14b79a661d573ac11e68c
:toc:
:toc-placement: preamble

image:https://img.shields.io/badge/license-cc%20zero-000000.svg?style=flat-square["CC Zero", link="http://creativecommons.org/publicdomain/zero/1.0/"]
pass:[<span class="image"><a class="image" href="https://maven-badges.herokuapp.com/maven-central/de.xn--ho-hia.storage_units/storage-units"><img src="https://img.shields.io/maven-central/v/de.xn--ho-hia.storage_units/storage-units.svg?style=flat-square" alt="Maven Central"></a></span>]
pass:[<span class="image"><a class="image" href="https://www.javadoc.io/doc/de.xn--ho-hia.storage_units/storage-units"><img src="https://www.javadoc.io/badge/de.xn--ho-hia.storage_units/storage-units.svg?style=flat-square&color=blue" alt="Read JavaDocs"></a></span>]
image:https://reposs.herokuapp.com/?path={github-org}/{project-name}&style=flat-square["Repository size"]
image:https://www.openhub.net/p/{project-name}/widgets/project_thin_badge.gif["Open Hub statistics", link="https://www.openhub.net/p/{project-name}"]

image:https://img.shields.io/travis/{github-org}/{project-name}/master.svg?style=flat-square["Build Status", link="https://travis-ci.org/{github-org}/{project-name}"]
image:https://img.shields.io/coveralls/{github-org}/{project-name}/master.svg?style=flat-square["Code Coverage", link="https://coveralls.io/github/{github-org}/{project-name}"]
image:https://img.shields.io/coverity/scan/{coverity-project}.svg?style=flat-square["Coverity Scan Result", link="https://scan.coverity.com/projects/{github-org}-{project-name}"]
image:https://img.shields.io/codacy/grade/{codacy-project}.svg?style=flat-square["Codacy Code Quality", link="https://www.codacy.com/app/mail_7/{project-name}"]
image:https://img.shields.io/badge/forkable-yes-brightgreen.svg?style=flat-square["Can this project be forked?", link="https://basicallydan.github.io/forkability/?u={github-org}&r={project-name}"]
image:https://img.shields.io/maintenance/yes/.svg?style=flat-square["Is this thing still maintained?"]
image:https://img.shields.io/bountysource/team/metio/activity.svg?style=flat-square["Bounties on open tickets", link="https://www.bountysource.com/teams/metio"]

https://www.java.com[Java] library for storage-/byte-units. All units defined in link:http://en.wikipedia.org/wiki/ISO/IEC_80000[ISO IEC 80000-13:2008] are supported, as well as other commonly found units, like 1 Kilobyte = 1024 Byte.

=== Features

* 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

==== Available Units

.Binary units
|===
| Name | Symbol | Exponential | Absolute | Class

| Byte
| B
| 2 ^0^ Byte
| 1 Byte
| `Byte`

| Kibibyte
| KiB
| 2 ^10^ Byte
| 1 024 Byte
| `Kibibyte`

| Mebibyte
| MiB
| 2 ^20^ Byte
| 1 048 576 Byte
| `Mebibyte`

| Gibibyte
| GiB
| 2 ^30^ Byte
| 1 073 741 824 Byte
| `Gibibyte`

| Tebibyte
| TiB
| 2 ^40^ Byte
| 1 099 511 627 776 Byte
| `Tebibyte`

| Pebibyte
| PiB
| 2 ^50^ Byte
| 1 125 899 906 842 624 Byte
| `Pebibyte`

| Exbibyte
| EiB
| 2 ^60^ Byte
| 1 152 921 504 606 846 976 Byte
| `Exbibyte`

| Zebibyte
| ZiB
| 2 ^70^ Byte
| 1 180 591 620 717 411 303 424 Byte
| `Zebibyte`

| Yobibyte
| YiB
| 2 ^80^ Byte
| 1 208 925 819 614 629 174 706 176 Byte
| `Yobibyte`
|===

.Decimal units
|===
| Name | Symbol | Exponential | Absolute | Class

| Byte
| kB
| 10 ^0^ Byte
| 1 Byte
| `Byte`

| Kilobyte
| kB
| 10 ^3^ Byte
| 1 000 Byte
| `Kilobyte`

| Megabyte
| MB
| 10 ^6^ Byte
| 1 000 000 Byte
| `Megabyte`

| Gigabyte
| GB
| 10 ^9^ Byte
| 1 000 000 000 Byte
| `Gigabyte`

| Terabyte
| TB
| 10 ^12^ Byte
| 1 000 000 000 000 Byte
| `Terabyte`

| Petabyte
| PB
| 10 ^15^ Byte
| 1 000 000 000 000 000 Byte
| `Petabyte`

| Exabyte
| EB
| 10 ^18^ Byte
| 1 000 000 000 000 000 000 Byte
| `Exabyte`

| Zettabyte
| ZB
| 10 ^21^ Byte
| 1 000 000 000 000 000 000 000 Byte
| `Zettabyte`

| Yottabyte
| YB
| 10 ^24^ Byte
| 1 000 000 000 000 000 000 000 000 Byte
| `Yottabyte`
|===

.Common units
|===
| Name | Symbol | Exponential | Absolute | Class

| Byte
| kB
| 2 ^0^ Byte
| 1 Byte
| `Byte`

| Kilobyte
| kB
| 2 ^10^ Byte
| 1 024 Byte
| `CommonKilobyte`

| Megabyte
| MB
| 2 ^20^ Byte
| 1 048 576 Byte
| `CommonMegabyte`

| Gigabyte
| GB
| 2 ^30^ Byte
| 1 073 741 824 Byte
| `CommonGigabyte`

| Terabyte
| TB
| 2 ^40^ Byte
| 1 099 511 627 776 Byte
| `CommonTerabyte`

| Petabyte
| PB
| 2 ^50^ Byte
| 1 125 899 906 842 624 Byte
| `CommonPetabyte`

| Exabyte
| EB
| 2 ^60^ Byte
| 1 152 921 504 606 846 976 Byte
| `CommonExabyte`

| Zettabyte
| ZB
| 2 ^70^ Byte
| 1 180 591 620 717 411 303 424 Byte
| `CommonZettabyte`

| Yottabyte
| YB
| 2 ^80^ Byte
| 1 208 925 819 614 629 174 706 176 Byte
| `CommonYottabyte`
|===

=== Development Status

All units are implemented. For future ideas, take a look at the link:https://github.com/sebhoss/storage-units/issues[open tickets] in case you are interested.


== 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`.

[source,java]
----
// 'long' based
Kilobyte unit = Kilobyte.valueOf(500) // 500 Byte or "0.50 kB"
Kibibyte unit = Kibibyte.valueOf(512) // 512 Byte or "0.50 KiB"
CommonKilobyte unit = CommonKilobyte.valueOf(512) // 512 Byte or "0.50 kB"

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"
CommonMegabyte unit = CommonMegabyte.valueOf(1_048_576) // 1 048 576 Byte or "1.00 MB"

// '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"
CommonKilobyte unit = CommonKilobyte.valueOf(BigInteger.valueOf(512)) // 512 Byte or "0.50 KB"

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"
CommonMegabyte unit = CommonMegabyte.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

[source,java]
----
// '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

[source,java]
----
// '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)
----

==== Common Units

[source,java]
----
// 'long' based
StorageUnit<?> unit = StorageUnits.commonValueOf(256) // CommonKilobyte (0.25 kB)
StorageUnit<?> unit = StorageUnits.commonValueOf(1048576) // CommonMebibyte (1.00 MB)

// 'BigInteger' based
StorageUnit<?> unit = StorageUnits.commonValueOf(BigInteger.valueOf(256)) // CommonKilobyte (0.25 kB)
StorageUnit<?> unit = StorageUnits.commonValueOf(BigInteger.valueOf(1048576)) // CommonMebibyte (1.00 MB)
----

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

[source,java]
----
import static de.xn__ho_hia.storage_unit.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

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

CommonKilobyte unit = commonKilobyte(1) // 1 024 Byte
CommonMegabyte unit = commonMegabyte(1) // 1 048 576 Byte
CommonGigabyte unit = commonGigabyte(1) // 1 073 741 824 Byte
CommonTerabyte unit = commonTerabyte(1) // 1 099 511 627 776 Byte
CommonPetabyte unit = commonPetabyte(1) // 1 125 899 906 842 624 Byte
CommonExabyte unit = commonExabyte(1) // 1 152 921 504 606 846 976 Byte
CommonZettabyte unit = commonZettabyte(1) // 1 180 591 620 717 411 303 424 Byte
CommonYottabyte unit = commonYottabyte(1) // 1 208 925 819 614 629 174 706 176 Byte
----

=== Add, Subtract, Multiply, Divide

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

[source,java]
----
import static de.xn__ho_hia.storage_unit.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.

[source,java]
----
import static de.xn__ho_hia.storage_unit.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.

[source,java]
----
import static de.xn__ho_hia.storage_unit.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.

[source,java]
----
import static de.xn__ho_hia.storage_unit.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"
kilobyte(1100).asBestMatchingCommonUnit() // "1.05 MB"
----

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

[source,java]
----
import static de.xn__ho_hia.storage_unit.StorageUnits.*;

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

=== Serialization

The storage-units-(eclipselink|mongodb|jackson) modules provide custom serializers to store storage units.

==== EclipseLink

Use any of the three converters like this:

[source, java]
----
@Entity
public class HardDisk implements Serializable {

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

@Basic
@Converter (
name="commonConverter",
converterClass=de.xn__ho_hia.storage_unit.eclipselink.CommonStorageUnitConverter.class
)
@Convert("commonConverter")
public StorageUnit<?> getUsedSize() {
return usedSize;
}

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

}
----

==== MongoDB

Use any of the three codecs like this:

[source, java]
----
CodecRegistry binaryRegistry = CodecRegistries.fromCodecs(new BinaryStorageUnitCodec(), ...);
CodecRegistry commonRegistry = CodecRegistries.fromCodecs(new CommonStorageUnitCodec(), ...);
CodecRegistry decimalRegistry = CodecRegistries.fromCodecs(new DecimalStorageUnitCodec(), ...);
----

==== Jackson

Use the provided `StorageUnitModule` like this:

[source, java]
----
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.COMMON));
objectMapper.registerModule(new StorageUnitModule(StorageUnitModule.PreferredUnitType.DECIMAL));
----

=== Integration

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

[source,xml,subs="attributes,verbatim"]
----
<dependencies>
<dependency>
<groupId>{project-group}</groupId>
<artifactId>storage-units</artifactId>
<version>${version.storage-units}</version>
</dependency>

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

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

<!-- Jackson ONLY -->
<dependency>
<groupId>{project-group}</groupId>
<artifactId>storage-units-jackson</artifactId>
<version>${version.storage-units}</version>
</dependency>
<!-- Jackson ONLY -->
</dependencies>
----

Replace `${version.storage-units}` with the link:++http://search.maven.org/#search%7Cga%7C1%7Cg%3Ade.xn--ho-hia.storage_units++[latest release]. This project follows the link:http://semver.org/[semantic versioning guidelines].

=== Compatibility

This project is compatible with the following Java versions:

.Java compatibility
|===
| | 1.X.Y | 2.X.Y | 3.X.Y | 4.X.Y

| Java 8
| ✓
| ✓
| ✓
| ✓

| Java 7
| ✓
|
|
|
|===

== Reference

Originally inspired by link:https://github.com/twitter/util#space[Twitters util] package.

== Alternatives

* link:https://github.com/JakeWharton/byteunits[Byte Units]
* link:https://github.com/trivago/triava[triava]

== License

To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.

You should have received a copy of the CC0 Public Domain Dedication along
with this software. If not, see http://creativecommons.org/publicdomain/zero/1.0/.

== Mirrors

* https://github.com/sebhoss/{project-name}
* https://bitbucket.org/sebhoss/{project-name}
* https://gitlab.com/sebastian.hoss/{project-name}
* http://v2.pikacode.com/sebhoss/{project-name}
* http://repo.or.cz/{project-name}.git