You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "Sammy Trojette (JIRA)" <ji...@apache.org> on 2016/11/01 10:50:58 UTC
[jira] [Comment Edited] (IO-373) FileUtils.byteCountToDisplaySize
improvement/rounding issues
[ https://issues.apache.org/jira/browse/IO-373?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15625001#comment-15625001 ]
Sammy Trojette edited comment on IO-373 at 11/1/16 10:50 AM:
-------------------------------------------------------------
Since this has just come up as an issue on our current project. I'd like to do a little necro here.
With this version, the displayed value is always set at least 3 numericals so: ####, ###, ##.# or #.##.
If anyone sees a serious issue, please give me a call.
{code:title=FileUtil.java|borderStyle=solid}
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import static org.apache.commons.io.FileUtils.*;
/**
* Custom Implementation of FileUtils.byteCountToDisplaySize to fix rounding bug
*/
public class FileUtil {
private static final RoundingMode ROUNDING_MODE = RoundingMode.HALF_UP;
enum FileSize {
EXABYTE("EB", ONE_EB_BI),
PETABYTE("PB", ONE_PB_BI),
TERABYTE("TB", ONE_TB_BI),
GIGABYTE("GB", ONE_GB_BI),
MEGABYTE("MB", ONE_MB_BI),
KILOBYTE("KB", ONE_KB_BI),
BYTE("bytes", BigInteger.ONE);
private final String unit;
private final BigInteger byteCount;
FileSize(String unit, BigInteger byteCount) {
this.unit = unit;
this.byteCount = byteCount;
}
private String unit() {
return unit;
}
private BigInteger byteCount() {
return byteCount;
}
}
/**
* Formats a file's size into a human readable format
*
* @param fileSize the file's size as BigInteger
* @return the size as human readable string
*/
public static String byteCountToDisplaySize(final BigInteger fileSize) {
String unit = FileSize.BYTE.unit;
BigDecimal fileSizeInUnit = BigDecimal.ZERO;
String val;
for (FileSize fs : FileSize.values()) {
BigDecimal size_bd = new BigDecimal(fileSize);
fileSizeInUnit = size_bd.divide(new BigDecimal(fs.byteCount), 5, ROUNDING_MODE);
if (fileSizeInUnit.compareTo(BigDecimal.ONE) >= 0) {
unit = fs.unit;
break;
}
}
// always round so that at least 3 numerics are displayed (###, ##.#, #.##)
if (fileSizeInUnit.divide(BigDecimal.valueOf(100.0), BigDecimal.ROUND_DOWN).compareTo(BigDecimal.ONE) >= 0) {
val = fileSizeInUnit.setScale(0, ROUNDING_MODE).toString();
} else if (fileSizeInUnit.divide(BigDecimal.valueOf(10.0), BigDecimal.ROUND_DOWN).compareTo(BigDecimal.ONE) >= 0) {
val = fileSizeInUnit.setScale(1, ROUNDING_MODE).toString();
} else {
val = fileSizeInUnit.setScale(2, ROUNDING_MODE).toString();
}
// trim zeros at the end
if (val.endsWith(".00")) {
val = val.substring(0, val.length() - 3);
} else if (val.endsWith(".0")) {
val = val.substring(0, val.length() - 2);
}
return String.format("%s %s", val, unit);
}
/**
* Formats a file's size into a human readable format
*
* @param fileSize the file's size as long
* @return the size as human readable string
*/
public static String byteCountToDisplaySize(final long fileSize) {
return byteCountToDisplaySize(BigInteger.valueOf(fileSize));
}
}
{code}
{code:title=FileUtilTest.java|borderStyle=solid}
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
* Test-Suite for FileUtil class
*/
public class FileUtilTest {
@Test
public void testByteCountToDisplaySizeLong() {
assertEquals(FileUtil.byteCountToDisplaySize(Character.MAX_VALUE), "64 KB");
assertEquals(FileUtil.byteCountToDisplaySize(Short.MAX_VALUE), "32 KB");
assertEquals(FileUtil.byteCountToDisplaySize(Integer.MAX_VALUE), "2 GB");
assertEquals(FileUtil.byteCountToDisplaySize(0), "0 bytes");
assertEquals(FileUtil.byteCountToDisplaySize(1), "1 bytes");
assertEquals(FileUtil.byteCountToDisplaySize(1023), "1023 bytes");
assertEquals(FileUtil.byteCountToDisplaySize(1024), "1 KB");
assertEquals(FileUtil.byteCountToDisplaySize(1030), "1.01 KB");
assertEquals(FileUtil.byteCountToDisplaySize(1224), "1.20 KB");
assertEquals(FileUtil.byteCountToDisplaySize(10240), "10 KB");
assertEquals(FileUtil.byteCountToDisplaySize(24832184), "23.7 MB");
assertEquals(FileUtil.byteCountToDisplaySize(new Long("38174914740")), "35.6 GB");
assertEquals(FileUtil.byteCountToDisplaySize(new Long("1374389534720")), "1.25 TB");
}
}
{code}
was (Author: strojette):
Since this has just come up as an issue on our current project. I'd like to do a little necro here.
With this version, the displayed value is always set at least 3 numericals so: ####, ###, ##.# or #.##.
If anyone sees a serious issue, please give me a call.
{code:title=FileUtil.java|borderStyle=solid}
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import static org.apache.commons.io.FileUtils.*;
/**
* Custom Implementation of FileUtils.byteCountToDisplaySize to fix rounding bug
*/
public class FileUtil {
private static final RoundingMode ROUNDING_MODE = RoundingMode.HALF_UP;
enum FileSize {
EXABYTE("EB", ONE_EB_BI),
PETABYTE("PB", ONE_PB_BI),
TERABYTE("TB", ONE_TB_BI),
GIGABYTE("GB", ONE_GB_BI),
MEGABYTE("MB", ONE_MB_BI),
KILOBYTE("KB", ONE_KB_BI),
BYTE("bytes", BigInteger.ONE);
private final String unit;
private final BigInteger byteCount;
FileSize(String unit, BigInteger byteCount) {
this.unit = unit;
this.byteCount = byteCount;
}
private String unit() {
return unit;
}
private BigInteger byteCount() {
return byteCount;
}
}
/**
* Formats a file's size into a human readable format
*
* @param fileSize the file's size as BigInteger
* @return the size as human readable string
*/
public static String byteCountToDisplaySize(final BigInteger fileSize) {
String unit = FileSize.BYTE.unit;
BigDecimal fileSizeInUnit = BigDecimal.ZERO;
String val;
for (FileSize fs : FileSize.values()) {
BigDecimal size_bd = new BigDecimal(fileSize);
fileSizeInUnit = size_bd.divide(new BigDecimal(fs.byteCount), 3, ROUNDING_MODE);
if (fileSizeInUnit.compareTo(BigDecimal.ONE) >= 0) {
unit = fs.unit;
break;
}
}
// always round so that at least 3 numerics are displayed (###, ##.#, #.##)
if (fileSizeInUnit.divide(BigDecimal.valueOf(100.0)).compareTo(BigDecimal.ONE) > 0) {
val = fileSizeInUnit.setScale(0, ROUNDING_MODE).toString();
} else if (fileSizeInUnit.divide(BigDecimal.valueOf(10.0)).compareTo(BigDecimal.ONE) > 0) {
val = fileSizeInUnit.setScale(1, ROUNDING_MODE).toString();
} else {
val = fileSizeInUnit.setScale(2, ROUNDING_MODE).toString();
}
// trim zeros at the end
if (val.endsWith(".00")) {
val = val.substring(0, val.length() - 3);
} else if (val.endsWith(".0")) {
val = val.substring(0, val.length() - 2);
}
return String.format("%s %s", val, unit);
}
/**
* Formats a file's size into a human readable format
*
* @param fileSize the file's size as long
* @return the size as human readable string
*/
public static String byteCountToDisplaySize(final long fileSize) {
return byteCountToDisplaySize(BigInteger.valueOf(fileSize));
}
}
{code}
{code:title=FileUtilTest.java|borderStyle=solid}
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
* Test-Suite for FileUtil class
*/
public class FileUtilTest {
@Test
public void testByteCountToDisplaySizeLong() {
assertEquals(FileUtil.byteCountToDisplaySize(Character.MAX_VALUE), "64 KB");
assertEquals(FileUtil.byteCountToDisplaySize(Short.MAX_VALUE), "32 KB");
assertEquals(FileUtil.byteCountToDisplaySize(Integer.MAX_VALUE), "2 GB");
assertEquals(FileUtil.byteCountToDisplaySize(0), "0 bytes");
assertEquals(FileUtil.byteCountToDisplaySize(1), "1 bytes");
assertEquals(FileUtil.byteCountToDisplaySize(1023), "1023 bytes");
assertEquals(FileUtil.byteCountToDisplaySize(1024), "1 KB");
assertEquals(FileUtil.byteCountToDisplaySize(1025), "1 KB");
assertEquals(FileUtil.byteCountToDisplaySize(24832184), "23.7 MB"); // real world test case
assertEquals(FileUtil.byteCountToDisplaySize(new Long("38174914740")), "35.6 GB"); // real world test case
assertEquals(FileUtil.byteCountToDisplaySize(new Long("1374389534720")), "1.25 TB");
}
}
{code}
> FileUtils.byteCountToDisplaySize improvement/rounding issues
> ------------------------------------------------------------
>
> Key: IO-373
> URL: https://issues.apache.org/jira/browse/IO-373
> Project: Commons IO
> Issue Type: Improvement
> Components: Utilities
> Affects Versions: 2.4
> Reporter: Mark
> Priority: Minor
> Attachments: byteCountToDisplaySize.patch, byteCountToHumanReadableGnu.patch
>
>
> Issue IO-226 is not fixed but closed.
> ?
> Here is my solution that also support a user-defined precision in terms of a maximum length of the digits part.
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)