All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.wl4g.infra.common.io.DataSize Maven / Gradle / Ivy

There is a newer version: 3.1.72
Show newest version
/*
 * Copyright 2002-2022 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.wl4g.infra.common.io;

import static org.apache.commons.lang3.StringUtils.isBlank;

import java.io.Serializable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Nullable;

import com.wl4g.infra.common.lang.Assert2;
import com.wl4g.infra.common.lang.StringUtils2;

/**
 * A data size, such as '12MB'.
 *
 * 

* This class models data size in terms of bytes and is immutable and * thread-safe. * *

* The terms and units used in this class are based on * binary prefixes * indicating multiplication by powers of 2. Consult the following table and the * Javadoc for {@link DataUnit} for details. * *

*

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
TermData SizeSize in Bytes
byte1B1
kilobyte1KB1,024
megabyte1MB1,048,576
gigabyte1GB1,073,741,824
terabyte1TB1,099,511,627,776
* * @author Stephane Nicoll * @author Sam Brannen * @since 5.1 * @see DataUnit * @see Copy of {@link org.springframework.util.unit.DataSize} */ @SuppressWarnings("serial") public final class DataSize implements Comparable, Serializable { /** * Bytes per Kilobyte. */ private static final long BYTES_PER_KB = 1024; /** * Bytes per Megabyte. */ private static final long BYTES_PER_MB = BYTES_PER_KB * 1024; /** * Bytes per Gigabyte. */ private static final long BYTES_PER_GB = BYTES_PER_MB * 1024; /** * Bytes per Terabyte. */ private static final long BYTES_PER_TB = BYTES_PER_GB * 1024; private final long bytes; private DataSize(long bytes) { this.bytes = bytes; } /** * Obtain a {@link DataSize} representing the specified number of bytes. * * @param bytes * the number of bytes, positive or negative * @return a {@link DataSize} */ public static DataSize ofBytes(long bytes) { return new DataSize(bytes); } /** * Obtain a {@link DataSize} representing the specified number of kilobytes. * * @param kilobytes * the number of kilobytes, positive or negative * @return a {@link DataSize} */ public static DataSize ofKilobytes(long kilobytes) { return new DataSize(Math.multiplyExact(kilobytes, BYTES_PER_KB)); } /** * Obtain a {@link DataSize} representing the specified number of megabytes. * * @param megabytes * the number of megabytes, positive or negative * @return a {@link DataSize} */ public static DataSize ofMegabytes(long megabytes) { return new DataSize(Math.multiplyExact(megabytes, BYTES_PER_MB)); } /** * Obtain a {@link DataSize} representing the specified number of gigabytes. * * @param gigabytes * the number of gigabytes, positive or negative * @return a {@link DataSize} */ public static DataSize ofGigabytes(long gigabytes) { return new DataSize(Math.multiplyExact(gigabytes, BYTES_PER_GB)); } /** * Obtain a {@link DataSize} representing the specified number of terabytes. * * @param terabytes * the number of terabytes, positive or negative * @return a {@link DataSize} */ public static DataSize ofTerabytes(long terabytes) { return new DataSize(Math.multiplyExact(terabytes, BYTES_PER_TB)); } /** * Obtain a {@link DataSize} representing an amount in the specified * {@link DataUnit}. * * @param amount * the amount of the size, measured in terms of the unit, * positive or negative * @return a corresponding {@link DataSize} */ public static DataSize of(long amount, DataUnit unit) { Assert2.notNull(unit, "Unit must not be null"); return new DataSize(Math.multiplyExact(amount, unit.size().toBytes())); } /** * Obtain a {@link DataSize} from a text string such as {@code 12MB} using * {@link DataUnit#BYTES} if no unit is specified. *

* Examples: * *

     * "12KB" -- parses as "12 kilobytes"
     * "5MB"  -- parses as "5 megabytes"
     * "20"   -- parses as "20 bytes"
     * 
* * @param text * the text to parse * @return the parsed {@link DataSize} * @see #parse(CharSequence, DataUnit) */ public static DataSize parse(String text) { return parse(text, null); } /** * Obtain a {@link DataSize} from a text string such as {@code 12MB} using * the specified default {@link DataUnit} if no unit is specified. *

* The string starts with a number followed optionally by a unit matching * one of the supported {@linkplain DataUnit suffixes}. *

* Examples: * *

     * "12KB" -- parses as "12 kilobytes"
     * "5MB"  -- parses as "5 megabytes"
     * "20"   -- parses as "20 kilobytes" (where the {@code
     * defaultUnit
     * } is {@link DataUnit#KILOBYTES})
     * 
* * @param text * the text to parse * @return the parsed {@link DataSize} */ public static DataSize parse(String text, @Nullable DataUnit defaultUnit) { Assert2.notNull(text, "Text must not be null"); try { Matcher matcher = DataSizeUtils.PATTERN.matcher(StringUtils2.trimAllWhitespace(text)); Assert2.state(matcher.matches(), "Does not match data size pattern"); DataUnit unit = DataSizeUtils.determineDataUnit(matcher.group(2), defaultUnit); long amount = Long.parseLong(matcher.group(1)); return DataSize.of(amount, unit); } catch (Exception ex) { throw new IllegalArgumentException("'" + text + "' is not a valid data size", ex); } } /** * Checks if this size is negative, excluding zero. * * @return true if this size has a size less than zero bytes */ public boolean isNegative() { return this.bytes < 0; } /** * Return the number of bytes in this instance. * * @return the number of bytes */ public long toBytes() { return this.bytes; } /** * Return the number of kilobytes in this instance. * * @return the number of kilobytes */ public long toKilobytes() { return this.bytes / BYTES_PER_KB; } /** * Return the number of megabytes in this instance. * * @return the number of megabytes */ public long toMegabytes() { return this.bytes / BYTES_PER_MB; } /** * Return the number of gigabytes in this instance. * * @return the number of gigabytes */ public long toGigabytes() { return this.bytes / BYTES_PER_GB; } /** * Return the number of terabytes in this instance. * * @return the number of terabytes */ public long toTerabytes() { return this.bytes / BYTES_PER_TB; } @Override public int compareTo(DataSize other) { return Long.compare(this.bytes, other.bytes); } @Override public String toString() { return String.format("%dB", this.bytes); } @Override public boolean equals(@Nullable Object other) { if (this == other) { return true; } if (other == null || getClass() != other.getClass()) { return false; } DataSize otherSize = (DataSize) other; return (this.bytes == otherSize.bytes); } @Override public int hashCode() { return Long.hashCode(this.bytes); } /** * Static nested class to support lazy loading of the {@link #PATTERN}. * * @since 5.3.21 */ private static class DataSizeUtils { /** * The pattern for parsing. */ private static final Pattern PATTERN = Pattern.compile("^([+\\-]?\\d+)([a-zA-Z]{0,2})$"); private static DataUnit determineDataUnit(String suffix, @Nullable DataUnit defaultUnit) { DataUnit defaultUnitToUse = (defaultUnit != null ? defaultUnit : DataUnit.BYTES); return (!isBlank(suffix) ? DataUnit.fromSuffix(suffix) : defaultUnitToUse); } } /** * A standard set of {@link DataSize} units. * *

* The unit prefixes used in this class are * binary prefixes * indicating multiplication by powers of 2. The following table displays * the enum constants defined in this class and corresponding values. * *

*

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
ConstantData SizePower of 2Size in Bytes
{@link #BYTES}1B2^01
{@link #KILOBYTES}1KB2^101,024
{@link #MEGABYTES}1MB2^201,048,576
{@link #GIGABYTES}1GB2^301,073,741,824
{@link #TERABYTES}1TB2^401,099,511,627,776
* * @author Stephane Nicoll * @author Sam Brannen * @since 5.1 * @see DataSize */ public static enum DataUnit { /** * Bytes, represented by suffix {@code B}. */ BYTES("B", DataSize.ofBytes(1)), /** * Kilobytes, represented by suffix {@code KB}. */ KILOBYTES("KB", DataSize.ofKilobytes(1)), /** * Megabytes, represented by suffix {@code MB}. */ MEGABYTES("MB", DataSize.ofMegabytes(1)), /** * Gigabytes, represented by suffix {@code GB}. */ GIGABYTES("GB", DataSize.ofGigabytes(1)), /** * Terabytes, represented by suffix {@code TB}. */ TERABYTES("TB", DataSize.ofTerabytes(1)); private final String suffix; private final DataSize size; DataUnit(String suffix, DataSize size) { this.suffix = suffix; this.size = size; } DataSize size() { return this.size; } /** * Return the {@link DataUnit} matching the specified {@code suffix}. * * @param suffix * one of the standard suffixes * @return the {@link DataUnit} matching the specified {@code suffix} * @throws IllegalArgumentException * if the suffix does not match the suffix of any of this * enum's constants */ public static DataUnit fromSuffix(String suffix) { for (DataUnit candidate : values()) { if (candidate.suffix.equals(suffix)) { return candidate; } } throw new IllegalArgumentException("Unknown data unit suffix '" + suffix + "'"); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy