I've found lots of information about converting raw byte information into a human-readable format, but I need to do the opposite, i.e. convert the String "1.6 GB" into the long value 1717990000. Is there an in-built/well-defined way to do this, or will I pretty much have to roll my own?
[Edit]: Here is my first stab...
static class ByteFormat extends NumberFormat {
@Override
public StringBuffer format(double arg0, StringBuffer arg1, FieldPosition arg2) {
// TODO Auto-generated method stub
return null;
}
@Override
public StringBuffer format(long arg0, StringBuffer arg1, FieldPosition arg2) {
// TODO Auto-generated method stub
return null;
}
@Override
public Number parse(String arg0, ParsePosition arg1) {
return parse (arg0);
}
@Override
public Number parse(String arg0) {
int spaceNdx = arg0.indexOf(" ");
double ret = Double.parseDouble(arg0.substring(0, spaceNdx));
String unit = arg0.substring(spaceNdx + 1);
int factor = 0;
if (unit.equals("GB")) {
factor = 1073741824;
}
else if (unit.equals("MB")) {
factor = 1048576;
}
else if (unit.equals("KB")) {
factor = 1024;
}
return ret * factor;
}
}
I write a file size human readable utility enum class, Hope it helps you!
/**
* The file size human readable utility class,
* provide mutual conversions from human readable size to byte size
*
* The similar function in stackoverflow, linked:
* https://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java?r=SearchResults
*
* Apache also provide similar function
* @see org.apache.commons.io.FileUtils#byteCountToDisplaySize(long)
*
* @author Ponfee
*/
public enum HumanReadables {
SI (1000, "B", "KB", "MB", "GB", "TB", "PB", "EB" /*, "ZB", "YB" */), //
BINARY(1024, "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"/*, "ZiB", "YiB"*/), //
;
private static final String FORMAT = "#,##0.##";
private static final Pattern PATTERN = Pattern.compile(".*[0-9]+.*");
private final int base;
private final String[] units;
private final long[] sizes;
HumanReadables(int base, String... units) {
this.base = base;
this.units = units;
this.sizes = new long[this.units.length];
this.sizes[0] = 1;
for (int i = 1; i < this.sizes.length; i++) {
this.sizes[i] = this.sizes[i - 1] * this.base; // Maths.pow(this.base, i);
}
}
/**
* Returns a string of bytes count human readable size
*
* @param size the size
* @return human readable size
*/
public strictfp String human(long size) {
if (size == 0) {
return "0" + this.units[0];
}
String signed = "";
if (size < 0) {
signed = "-";
size = size == Long.MIN_VALUE ? Long.MAX_VALUE : -size;
}
/*int unit = (int) Maths.log(size, this.base);
return signed + format(size / Math.pow(this.base, unit)) + " " + this.units[unit];*/
int unit = find(size);
return new StringBuilder(13) // 13 max length like as "-1,023.45 GiB"
.append(signed)
.append(formatter().format(size / (double) this.sizes[unit]))
.append(" ")
.append(this.units[unit])
.toString();
}
public strictfp long parse(String size) {
return parse(size, false);
}
/**
* Parse the readable byte count, allowed suffix units: "1", "1B", "1MB", "1MiB", "1M"
*
* @param size the size
* @param strict the strict, if BINARY then verify whether contains "i"
* @return a long value bytes count
*/
public strictfp long parse(String size, boolean strict) {
if (size == null || size.isEmpty()) {
return 0L;
}
if (!PATTERN.matcher(size).matches()) {
throw new IllegalArgumentException("Invalid format [" + size + "]");
}
String str = size = size.trim();
long factor = this.sizes[0];
switch (str.charAt(0)) {
case '+': str = str.substring(1); break;
case '-': str = str.substring(1); factor = -1L; break;
}
int end = 0, lastPos = str.length() - 1;
// last character isn't a digit
char c = str.charAt(lastPos - end);
if (c == 'i') {
// last pos cannot end with "i"
throw new IllegalArgumentException("Invalid format [" + size + "], cannot end with \"i\".");
}
if (c == 'B') {
end++;
c = str.charAt(lastPos - end);
boolean flag = isBlank(c);
while (isBlank(c) && end < lastPos) {
end++;
c = str.charAt(lastPos - end);
}
// if "B" head has space char, then the first head non space char must be a digit
if (flag && !Character.isDigit(c)) {
throw new IllegalArgumentException("Invalid format [" + size + "]: \"" + c + "\".");
}
}
if (!Character.isDigit(c)) {
// if not a digit character, then assume is a unit character
if (c == 'i') {
if (this == SI) {
// SI cannot contains "i"
throw new IllegalArgumentException("Invalid SI format [" + size + "], cannot contains \"i\".");
}
end++;
c = str.charAt(lastPos - end);
} else {
if (this == BINARY && strict) {
// if strict, then BINARY must contains "i"
throw new IllegalArgumentException("Invalid BINARY format [" + size + "], miss character \"i\".");
}
}
switch (c) {
case 'K': factor *= this.sizes[1]; break;
case 'M': factor *= this.sizes[2]; break;
case 'G': factor *= this.sizes[3]; break;
case 'T': factor *= this.sizes[4]; break;
case 'P': factor *= this.sizes[5]; break;
case 'E': factor *= this.sizes[6]; break;
/*
case 'Z': factor *= this.bytes[7]; break;
case 'Y': factor *= this.bytes[8]; break;
*/
default: throw new IllegalArgumentException("Invalid format [" + size + "]: \"" + c + "\".");
}
do {
end++;
c = str.charAt(lastPos - end);
} while (isBlank(c) && end < lastPos);
}
str = str.substring(0, str.length() - end);
try {
return (long) (factor * formatter().parse(str).doubleValue());
} catch (NumberFormatException | ParseException e) {
throw new IllegalArgumentException("Failed to parse [" + size + "]: \"" + str + "\".");
}
}
public int base() {
return this.base;
}
public String[] units() {
return Arrays.copyOf(this.units, this.units.length);
}
public long[] sizes() {
return Arrays.copyOf(this.sizes, this.sizes.length);
}
private int find(long bytes) {
int n = this.sizes.length;
for (int i = 1; i < n; i++) {
if (bytes < this.sizes[i]) {
return i - 1;
}
}
return n - 1;
}
private DecimalFormat formatter() {
return new DecimalFormat(FORMAT);
}
private boolean isBlank(char c) {
return c == ' ' || c == '\t';
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With