commons-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Mark (JIRA)" <j...@apache.org>
Subject [jira] [Comment Edited] (IO-373) FileUtils.byteCountToDisplaySize improvement/rounding issues
Date Sun, 21 Apr 2013 12:39:16 GMT

    [ https://issues.apache.org/jira/browse/IO-373?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13612282#comment-13612282
] 

Mark edited comment on IO-373 at 4/21/13 12:38 PM:
---------------------------------------------------

Here is a variant that is able to let the user specify the maximum number of characters used
to display the digits part of the displayed string. The rounding also makes a lot of sense
to me.

{code}
public class FileUtils {

    private static final int DEFAULT_MAXCHARS = 3;
    private static final BigDecimal KILO_DIVISOR = new BigDecimal(1024L);

    enum SizeSuffix {

        B, KB, MB, GB, TB, PB, EB, ZB, YB;
    }

    /**
     * Adopted and improved version of
     * {@link org.apache.commons.io.FileUtils#byteCountToDisplaySize(BigInteger)}.
     * <p>
     * Warning! it is not advised to use <code>maxChars &lt; 3</code> because
it produces
     * correctly rounded, but non-intuitive results like "0 KB" for 100 bytes.
     * 
     * @see https://issues.apache.org/jira/browse/IO-226 - should the rounding be changed?
     * @see https://issues.apache.org/jira/browse/IO-373
     * @param size
     * @param maxChars maximum length of digit part, ie. '1.2'
     * @return rounded byte size as {@link java.lang.String}
     */
    public static String byteCountToDisplaySize(BigInteger size, int maxChars) {
        String displaySize;
        BigDecimal bdSize = new BigDecimal(size);
        SizeSuffix selectedSuffix = SizeSuffix.B;
        for (SizeSuffix sizeSuffix : SizeSuffix.values()) {
            if (sizeSuffix.equals(SizeSuffix.B)) {
                continue;
            }
            if (bdSize.setScale(0, RoundingMode.HALF_UP).toString().length() <= maxChars)
{
                break;
            }
            selectedSuffix = sizeSuffix;
            bdSize = bdSize.divide(KILO_DIVISOR);
        }
        displaySize = bdSize.setScale(0, RoundingMode.HALF_UP).toString();
        if (displaySize.length() < maxChars - 1) {
            displaySize = bdSize.setScale(
                    maxChars - 1 - displaySize.length(), RoundingMode.HALF_UP).toString();
        }
        return displaySize + " " + selectedSuffix.toString();
    }

    /**
     * See {@link #byteCountToDisplaySize(BigInteger,int)}.
     * @param size
     * @param maxChars
     * @return
     */
    public static String byteCountToDisplaySize(long size, int maxChars) {
        return byteCountToDisplaySize(BigInteger.valueOf(size), maxChars);
    }

}
{code}

{code}
public class FileUtilsTest {

    /**
     * Test of byteCountToDisplaySize method, of class FileUtils.
     */
    @Test
    public void testByteCountToDisplaySize() {
        assertEquals("99 B", FileUtils.byteCountToDisplaySize(99L));
        assertEquals("999 B", FileUtils.byteCountToDisplaySize(999L));
        assertEquals("1.0 KB", FileUtils.byteCountToDisplaySize(1000L));
        assertEquals("1.0 KB", FileUtils.byteCountToDisplaySize(1023L));
        assertEquals("1.1 KB", FileUtils.byteCountToDisplaySize(1124L));
        assertEquals("1.1 KB", FileUtils.byteCountToDisplaySize(1164L));
        assertEquals("999 KB", FileUtils.byteCountToDisplaySize(1024L * 999L + 511L));
        assertEquals("1.0 MB", FileUtils.byteCountToDisplaySize(1024L * 999L + 512L));
        assertEquals("1.0 MB", FileUtils.byteCountToDisplaySize(1024L * 1024L - 1L));
        assertEquals("1.0 GB", FileUtils.byteCountToDisplaySize(1024L * 1024L * 1024L - 1L));
        assertEquals("1.0 TB", FileUtils.byteCountToDisplaySize(1024L * 1024L * 1024L * 1024L
- 1L));
        assertEquals("1.0 PB", FileUtils.byteCountToDisplaySize(1024L * 1024L * 1024L * 1024L
* 1024L - 1L));
        assertEquals("1.0 EB", FileUtils.byteCountToDisplaySize(
                1024L * 1024L * 1024L * 1024L * 1024L * 1024L - 1L));
        BigInteger bi = BigInteger.valueOf(1024L * 1024L * 1024L * 1024L * 1024L * 1024L);
        bi = bi.multiply(BigInteger.valueOf(1024L));
        assertEquals("1.0 ZB", FileUtils.byteCountToDisplaySize(bi));
        bi = bi.multiply(BigInteger.valueOf(1024L));
        assertEquals("1.0 YB", FileUtils.byteCountToDisplaySize(bi));
        bi = bi.multiply(BigInteger.valueOf(1024L));
        assertEquals("1024 YB", FileUtils.byteCountToDisplaySize(bi));
        bi = bi.multiply(BigInteger.valueOf(1024L));
        assertEquals("1048576 YB", FileUtils.byteCountToDisplaySize(bi));

        assertEquals("0 KB", FileUtils.byteCountToDisplaySize(100L, 2));
        assertEquals("1 KB", FileUtils.byteCountToDisplaySize(1000L, 2));
        assertEquals("1 KB", FileUtils.byteCountToDisplaySize(1023L, 2));
        assertEquals("20 KB", FileUtils.byteCountToDisplaySize(19L * 1024L + 512L, 2));
        assertEquals("20 KB", FileUtils.byteCountToDisplaySize(19L * 1024L + 512L, 3));
        assertEquals("19.5 KB", FileUtils.byteCountToDisplaySize(19L * 1024L + 512L, 4));
        assertEquals("196 KB", FileUtils.byteCountToDisplaySize(195L * 1024L + 512L, 4));

        assertEquals("0 MB", FileUtils.byteCountToDisplaySize(19L * 1024L + 512L, 1));

        assertEquals("1 KB", org.apache.commons.io.FileUtils.byteCountToDisplaySize(2047));
    }
}
{code}
                
      was (Author: rnfm7avr):
    Here is a variant that is able to let the user specify the maximum number of characters
used to display the digits part of the displayed string. The rounding also makes a lot of
sense to me.

{code}
public class FileUtils {

    private static final int DEFAULT_MAXCHARS = 3;
    private static final BigDecimal KILO_DIVISOR = new BigDecimal(1024L);

    enum SizeSuffix {

        B, KB, MB, GB, TB, PB, EB, ZB, YB;
    }

    /**
     * Adopted and improved version of
     * {@link org.apache.commons.io.FileUtils#byteCountToDisplaySize(BigInteger)}.
     * <p>
     * Warning! it is not advised to use <code>maxChars &lt; 3</code> because
it produces
     * correctly rounded, but non-intuitive results like "0 KB" for 100 bytes.
     *
     * @see https://issues.apache.org/jira/browse/IO-226 - should the rounding be changed?
     * @param size
     * @param maxChars maximum length of digit part, ie. '1.2'
     * @return rounded byte size as {@link java.lang.String}
     */
    public static String byteCountToDisplaySize(BigInteger size, int maxChars) {
        String displaySize;
        BigDecimal bdSize = new BigDecimal(size);
        SizeSuffix selectedSuffix = SizeSuffix.B;
        for (SizeSuffix sizeSuffix : SizeSuffix.values()) {
            if (sizeSuffix.equals(SizeSuffix.B)) {
                continue;
            }
            if (bdSize.setScale(0, RoundingMode.HALF_UP).toString().length() <= maxChars)
{
                break;
            }
            selectedSuffix = sizeSuffix;
            bdSize = bdSize.divide(KILO_DIVISOR);
        }
        displaySize = bdSize.setScale(0, RoundingMode.HALF_UP).toString();
        if (displaySize.length() < maxChars - 1) {
            displaySize = bdSize.setScale(
                    maxChars - 1 - displaySize.length(), RoundingMode.HALF_UP).toString();
        }
        return displaySize + " " + selectedSuffix.toString();
    }

    public static String byteCountToDisplaySize(BigInteger size) {
        return byteCountToDisplaySize(size, DEFAULT_MAXCHARS);
    }

    public static String byteCountToDisplaySize(long size, int maxChars) {
        return byteCountToDisplaySize(BigInteger.valueOf(size), maxChars);
    }

    public static String byteCountToDisplaySize(long size) {
        return byteCountToDisplaySize(BigInteger.valueOf(size), DEFAULT_MAXCHARS);
    }
}
{code}

{code}
public class FileUtilsTest {

    /**
     * Test of byteCountToDisplaySize method, of class FileUtils.
     */
    @Test
    public void testByteCountToDisplaySize() {
        assertEquals("99 B", FileUtils.byteCountToDisplaySize(99L));
        assertEquals("999 B", FileUtils.byteCountToDisplaySize(999L));
        assertEquals("1.0 KB", FileUtils.byteCountToDisplaySize(1000L));
        assertEquals("1.0 KB", FileUtils.byteCountToDisplaySize(1023L));
        assertEquals("1.1 KB", FileUtils.byteCountToDisplaySize(1124L));
        assertEquals("1.1 KB", FileUtils.byteCountToDisplaySize(1164L));
        assertEquals("999 KB", FileUtils.byteCountToDisplaySize(1024L * 999L + 511L));
        assertEquals("1.0 MB", FileUtils.byteCountToDisplaySize(1024L * 999L + 512L));
        assertEquals("1.0 MB", FileUtils.byteCountToDisplaySize(1024L * 1024L - 1L));
        assertEquals("1.0 GB", FileUtils.byteCountToDisplaySize(1024L * 1024L * 1024L - 1L));
        assertEquals("1.0 TB", FileUtils.byteCountToDisplaySize(1024L * 1024L * 1024L * 1024L
- 1L));
        assertEquals("1.0 PB", FileUtils.byteCountToDisplaySize(1024L * 1024L * 1024L * 1024L
* 1024L - 1L));
        assertEquals("1.0 EB", FileUtils.byteCountToDisplaySize(
                1024L * 1024L * 1024L * 1024L * 1024L * 1024L - 1L));
        BigInteger bi = BigInteger.valueOf(1024L * 1024L * 1024L * 1024L * 1024L * 1024L);
        bi = bi.multiply(BigInteger.valueOf(1024L));
        assertEquals("1.0 ZB", FileUtils.byteCountToDisplaySize(bi));
        bi = bi.multiply(BigInteger.valueOf(1024L));
        assertEquals("1.0 YB", FileUtils.byteCountToDisplaySize(bi));
        bi = bi.multiply(BigInteger.valueOf(1024L));
        assertEquals("1024 YB", FileUtils.byteCountToDisplaySize(bi));
        bi = bi.multiply(BigInteger.valueOf(1024L));
        assertEquals("1048576 YB", FileUtils.byteCountToDisplaySize(bi));

        assertEquals("0 KB", FileUtils.byteCountToDisplaySize(100L, 2));
        assertEquals("1 KB", FileUtils.byteCountToDisplaySize(1000L, 2));
        assertEquals("1 KB", FileUtils.byteCountToDisplaySize(1023L, 2));
        assertEquals("20 KB", FileUtils.byteCountToDisplaySize(19L * 1024L + 512L, 2));
        assertEquals("20 KB", FileUtils.byteCountToDisplaySize(19L * 1024L + 512L, 3));
        assertEquals("19.5 KB", FileUtils.byteCountToDisplaySize(19L * 1024L + 512L, 4));
        assertEquals("196 KB", FileUtils.byteCountToDisplaySize(195L * 1024L + 512L, 4));

        assertEquals("0 MB", FileUtils.byteCountToDisplaySize(19L * 1024L + 512L, 1));

        assertEquals("1 KB", org.apache.commons.io.FileUtils.byteCountToDisplaySize(2047));
    }
}
{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
>
> 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 is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

Mime
View raw message