Commons IO
  1. Commons IO
  2. IO-226

Rounding issue with byteCountToDisplaySize(long size)

    Details

    • Type: Improvement Improvement
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 2.0
    • Component/s: Utilities
    • Labels:
      None

      Description

      I do not understand the byteCountToDisplaySize(long size) method which is in class FileUtils of the package org.apache.commons.io.
      If the parameter size is 2047 , the method will return 1 KB.Why it will lose precision.
      I read the code.
      Maybe it is a bug?

        Activity

        shu kai yuan created issue -
        Sebb made changes -
        Field Original Value New Value
        Issue Type Bug [ 1 ] Improvement [ 4 ]
        Niall Pemberton made changes -
        Status Open [ 1 ] Resolved [ 5 ]
        Fix Version/s 2.0 [ 12312961 ]
        Resolution Fixed [ 1 ]
        Mark Thomas made changes -
        Workflow jira [ 12488110 ] Default workflow, editable Closed status [ 12601790 ]
        Gary Gregory made changes -
        Summary question with byteCountToDisplaySize(long size) Rounding issue with byteCountToDisplaySize(long size)
        Henri Yandell made changes -
        Status Resolved [ 5 ] Closed [ 6 ]
        Brice McIver made changes -
        Attachment roundedByteCountToDisplaySize.patch [ 12542305 ]
        Mark made changes -
        Comment [ 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;
            }

            /**
             * Adopted and improved version of
             * {@link org.apache.commons.io.FileUtils#byteCountToDisplaySize(BigInteger)}.
             *
             * @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()) {
                    selectedSuffix = sizeSuffix;
                    if (bdSize.setScale(0, RoundingMode.HALF_UP).toString().length() <= maxChars) {
                        break;
                    }
                    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}
        // CHECKSTYLE IGNORE MagicNumber FOR NEXT 1000 LINES
        public class FileUtilsTest {

            /**
             * Test of byteCountToDisplaySize method, of class FileUtils.
             */
            @Test
            public void testByteCountToDisplaySize() {
                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));

                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));
            }
        }
        {code} ]

          People

          • Assignee:
            Unassigned
            Reporter:
            shu kai yuan
          • Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development