snippetjavaMinor
Convert a formatted file size to bytes
Viewed 0 times
fileconvertsizeformattedbytes
Problem
I needed to convert a formatted file size back into its length in bytes. I came up with the following code but want it reviewed:
Some tests:
Output:
/**
* Converts a formatted size to its equivalent in bytes.
*
* @param size
* The formatted file size. Examples: "125.5 MB", "1KiB", "0.8 GB"
* @return
* @throws NumberFormatException
*/
public static long getBytesFromFormattedSize(final String size) throws NumberFormatException {
final String[] arr = size.toUpperCase().split(" ");
if (arr.length != 2) {
if (arr.length == 1 && Character.isDigit(size.charAt(0))) {
// Treat this as a formatted size missing the space.
return getBytesFromSize(size);
}
throw new IllegalArgumentException("Expected ' ', got '" + size + "'");
}
final char unit = arr[1].charAt(0);
if (unit == 'B') {
return Integer.parseInt(arr[0]);
}
final int bytes = arr[1].length() == 3 && arr[1].charAt(1) == 'I' ? 1000 : 1024;
final char[] units = {
'K', 'M', 'G', 'T', 'P', 'E'
};
int exp = 1;
for (final char ch : units) {
if (unit == ch) {
break;
}
exp++;
}
return (long) (Double.parseDouble(arr[0]) * Math.pow(bytes, exp));
}
private static long getBytesFromSize(final String size) {
String fixedSize = "";
for (final char c : size.toCharArray()) {
if (Character.isLetter(c) && !fixedSize.contains(" ")) {
fixedSize += ' ';
}
fixedSize += c;
}
return getBytesFromFormattedSize(fixedSize);
}Some tests:
String[] sizes = {
"1 KB", "100 MB", "100MiB", "1 GB", "100B", "1.5 MB"
};
for (String size : sizes) {
System.out.println(String.format("%s = %d bytes", size, getBytesFromFormattedSize(size)));
}Output:
1 KB = 1024 bytes
100 MB = 104857600 bytes
100MiB = 100000000 bytes
1 GB = 1073741824 bytes
100B = 100 bytes
1.5 MB = 1572864 bytesSolution
- The function throws
NumberFormatExceptionandIllegalArgumentException.
-
Your implementation caters to your edge cases, take these for example:
- 1Kb (Do you wish to handle bits). This gets converted to 1KB (unwantedly).
- 1M iB (Incorrect position of space)
- 1 (No units).
Not sure if the input is manual or system feeded.
Why not have a function that validates the input and if it can be tailored (1MiB), it returns a operable string.
- A Map can be used instead of the units' char array, for loop and
Math.powfor each input.
-
getBytesFromFormattedSize() calls getBytesFromSize() which again calls getBytesFromFormattedSize(). Instead a flow as this would look clean. getBytesFromFormattedSize(){
//Get a valid string (if possible) (in two forms value and unit)
// Proceed thereof.
}fixedSize.contains()has an O(n) time complexity. Instead a boolean would easily suffice the otherwise redundant call once we insert a space.
- Names such as
arr,size,bytesare ignorant to their puprose.
- Too much of hard coded values to actually understand the flow.
- Should
Ireturn 1000? http://en.wikipedia.org/wiki/Mebibyte
return Integer.parseInt(arr[0]);assumes that the value would not be greater than INT_MAX? Does the input guarantee that?
- If
sizeis an empty string, charAt(0) could give exceptionIndexOutOfBoundsException().
Code Snippets
getBytesFromFormattedSize(){
//Get a valid string (if possible) (in two forms value and unit)
// Proceed thereof.
}Context
StackExchange Code Review Q#77697, answer score: 3
Revisions (0)
No revisions yet.