【问题标题】:Converting KB to MB, GB, TB dynamically动态将 KB 转换为 MB、GB、TB
【发布时间】:2012-11-12 10:55:50
【问题描述】:
public String size(int size){
    String hrSize = "";
    int k = size;
    double m = size/1024;
    double g = size/1048576;
    double t = size/1073741824;

    DecimalFormat dec = new DecimalFormat("0.00");

    if (k>0)
    {

        hrSize = dec.format(k).concat("KB");

    }
    if (m>0)
    {

        hrSize = dec.format(m).concat("MB");
    }
    if (g>0)
    {

        hrSize = dec.format(g).concat("GB");
    }
    if (t>0)
    {

        hrSize = dec.format(t).concat("TB");
    }

    return hrSize;
    }

这是一个应该以 GB、MB、KB 或 TB 为单位返回大小的方法。输入值以 KB 为单位。 例如 1245 的结果应该是 1.21MB,但我得到的是 1.00MB。

【问题讨论】:

    标签: java int double division operation


    【解决方案1】:

    修改后的版本。只调用一次格式。包括“字节”。

    public static String formatFileSize(long size) {
        String hrSize = null;
    
        double b = size;
        double k = size/1024.0;
        double m = ((size/1024.0)/1024.0);
        double g = (((size/1024.0)/1024.0)/1024.0);
        double t = ((((size/1024.0)/1024.0)/1024.0)/1024.0);
    
        DecimalFormat dec = new DecimalFormat("0.00");
    
        if ( t>1 ) {
            hrSize = dec.format(t).concat(" TB");
        } else if ( g>1 ) {
            hrSize = dec.format(g).concat(" GB");
        } else if ( m>1 ) {
            hrSize = dec.format(m).concat(" MB");
        } else if ( k>1 ) {
            hrSize = dec.format(k).concat(" KB");
        } else {
            hrSize = dec.format(b).concat(" Bytes");
        }
    
        return hrSize;
    }
    

    【讨论】:

    • 从 2020 年开始,我们应该开始考虑 PB、PB、PB EB、EB、EB、ZB、Zettabyte、Zettabytes YB、yottabyte、yottabytes
    【解决方案2】:

    您正在执行integer division。所以除法的结果也是integer。并且小数部分被截断。

    so, 1245 / 1024 = 1
    

    将您的部门更改为floating point division:-

    double m = size/1024.0;
    double g = size/1048576.0;
    double t = size/1073741824.0;
    

    另外,你的比较是错误的。您应该与1 进行比较。

    if (m > 1), if (t > 1), if (g > 1)
    

    理想情况下,我会将您的比较更改为:-

        if (t > 1) {
            hrSize = dec.format(t).concat("TB");
        } else if (g > 1) {
            hrSize = dec.format(g).concat("GB");
        } else if (m > 1) {
            hrSize = dec.format(m).concat("MB");
        } else {
            hrSize = dec.format(size).concat("KB");
        }
    

    你需要先与较高的单元比较,然后再移动到较低的单元。

    【讨论】:

    • @pedja:对于mgt,使用else if 而不仅仅是if,因为即使是一个小文件也可能是0.00000000001 TB(大于零)。
    • @GregHewgill..啊!没注意到。
    • @pedja.. 你应该与1 进行比较,而您正在与0 进行比较。将所有 if 更改为 k > 1, g > 1, ...
    • @pedja.. 检查已编辑的帖子。您需要稍微修改您的if 比较。
    • 嗯,有很多可能的方式来实现你想要的功能。听起来您终于找到了适合您的实现方式。
    【解决方案3】:

    我喜欢这个:

    public static String getDynamicSpace(long diskSpaceUsed)
    {
        if (diskSpaceUsed <= 0) {
            return "0";
        }
    
        final String[] units = new String[] { "B", "KiB", "MiB", "GiB", "TiB" };
        int digitGroups = (int) (Math.log10(diskSpaceUsed) / Math.log10(1024));
        return new DecimalFormat("#,##0.#").format(diskSpaceUsed / Math.pow(1024, digitGroups))
                + " " + units[digitGroups];
    }
    

    【讨论】:

    • 不是一个安全的函数! Crashlytics 报告:Fatal Exception: java.lang.ArrayIndexOutOfBoundsException length=5; index=319302040
    • “不安全”是什么意思?此功能对于合理的数字是安全的,并且可以按照问题中提出的目的(从 B 到 TiB)工作。如果您需要更多大小,可以添加到数组“PiB”和“EiB”以测量 pebibytes 和 exbibytes,直到 9,223,372,036,854,775,807 字节。对于更大的数字,该功能需要重新设计。无论如何,您打算如何解决它以使其“更安全”(无论这意味着什么)?
    【解决方案4】:

    问题是您使用的是整数除法。将您的代码更改为:

    double m = size/1024.0;
    double g = size/1048576.0;
    double t = size/1073741824.0;
    

    在您的原始代码中,double m = size/1024 会将整数 size 除以 1024,将结果截断为整数,然后再将其转换为 double。这就是小数部分丢失的原因。

    【讨论】:

      【解决方案5】:

      你正在执行整数除法,

      即 31/15 将导致 2,而不是 2.whatever

      只需在数字后面加上Dd,表示它是双精度数,就可以了

      double m = size/1024D;
      double g = size/1048576D;
      double t = size/1073741824D;
      

      【讨论】:

        【解决方案6】:

        要做到这一点并不容易。 Rohit Jain 提到了整数运算。舍入也可能是一个问题,因为总是向下舍入可能是不可取的。我建议去寻找一个可用的解决方案,比如在 triava 库中。

        它可以在 3 种不同的系统(SI、IEC、JEDEC)和各种输出选项中以任意精度格式化数字。以下是来自triava unit tests 的一些代码示例:

        UnitFormatter.formatAsUnit(1126, UnitSystem.SI, "B");
        // = "1.13kB"
        UnitFormatter.formatAsUnit(2094, UnitSystem.IEC, "B");
        // = "2.04KiB"
        

        打印精确的千克、兆值(此处为 W = 瓦特):

        UnitFormatter.formatAsUnits(12_000_678, UnitSystem.SI, "W", ", ");
        // = "12MW, 678W"
        

        您可以传递一个 DecimalFormat 来自定义输出:

        UnitFormatter.formatAsUnit(2085, UnitSystem.IEC, "B", new DecimalFormat("0.0000"));
        // = "2.0361KiB"
        

        对于公斤或兆值的任意操作,您可以将它们拆分为组件:

        UnitComponent uc = new  UnitComponent(123_345_567_789L, UnitSystem.SI);
        int kilos = uc.kilo(); // 567
        int gigas = uc.giga(); // 123
        

        【讨论】:

          【解决方案7】:
          class ConverterUtils{
              public static void main(String[] args) {
                  System.out.println(getSize(1234567));
              }
              public static String getSize(long size) {
                  String s = "";
                  double kb = size / 1024;
                  double mb = kb / 1024;
                  double gb = mb / 1024;
                  double tb = gb / 1024;
                  if(size < 1024L) {
                      s = size + " Bytes";
                  } else if(size >= 1024 && size < (1024L * 1024)) {
                      s =  String.format("%.2f", kb) + " KB";
                  } else if(size >= (1024L * 1024) && size < (1024L * 1024 * 1024)) {
                      s = String.format("%.2f", mb) + " MB";
                  } else if(size >= (1024L * 1024 * 1024) && size < (1024L * 1024 * 1024 * 1024)) {
                      s = String.format("%.2f", gb) + " GB";
                  } else if(size >= (1024L * 1024 * 1024 * 1024)) {
                      s = String.format("%.2f", tb) + " TB";
                  }
                  return s;
              }
          }
          

          为了更好地理解 - https://www.techspot.com/news/68482-quickly-convert-between-storage-size-units-kb-mb.html

          【讨论】:

            【解决方案8】:
            public class FileSizeCalculator {
            
                String[] fileSizeUnits = {"bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"};
            
                public static void main(String[] args) {
                    FileSizeCalculator fs = new FileSizeCalculator();
                    String properFileSize = fs.calculateProperFileSize(2362232012l);
                    System.out.println("Proper file size: " + properFileSize);
                }
            
                public String calculateProperFileSize(long noOfBytes){
                    String sizeToReturn = "";// = FileUtils.byteCountToDisplaySize(bytes), unit = "";
                    double bytes = noOfBytes;
                    int index = 0;
                    for(index = 0; index < fileSizeUnits.length; index++){
                        if(bytes < 1024){
                            break;
                        }
                        bytes = bytes / 1024;
                    }
                    sizeToReturn = String.valueOf(bytes) + " " + fileSizeUnits[index];
                    return sizeToReturn;
                }
            }
            

            只需添加更多文件单元(如果有任何缺失),您就会看到单元大小达到该单元(如果您的文件有那么长)

            【讨论】:

            • 非常好的答案!谢谢Vishwajit
            • 我有一个问题:2362232012 这个以字节为单位的数字等于 2.362232012 Gigabytes 但传递字节数我得到一个错误,指出整数太大?有什么想法吗?
            • @Inside4ndroid,将字节数的数据类型更改为“long”数据类型。所以不会报错。我正在编辑我的代码并将方法参数从 double 类型更改为 long 类型。
            • 在 EiB 之前,单位应该是 KiB、MiB 等,因为 long 不能测量超过 8 exbibytes(-1 字节)。
            【解决方案9】:

            我的基本版本(你可以定义一些常量而不是一直计算 POW):

            public static String GetFolderSizeHuman(long aBytes)
            {
              if (aBytes < 1024 * 1024) 
                return aBytes + " KB";
              else if (aBytes < Math.pow(2, 20) * 1024)
                return (int) aBytes / Math.pow(2, 20) + " MB";
              else if (aBytes < Math.pow(2, 30) * 1024 )
                return kGbTbFormatter.format(aBytes / Math.pow(2, 30)) + " GB";
              else if (aBytes < Math.pow(2, 40) * 1024)
                return kGbTbFormatter.format(aBytes / Math.pow(2, 40)) + " TB";
            
              else return "N/A (1TB?)";
            }
            

            【讨论】:

              【解决方案10】:

              bickster's answer 工作得很好,但问题是它返回的结果类似于45.00 Bytes12.00 KB。我认为,如果最后一个十进制数字为零,则应删除它们。所以不是45.00 Bytes12.00 KB,而是45 B12 KB(注意Bytes已更改为B。这只是为了统一,因为我们有KB、MB等而不是千字节,兆字节等)。

              private boolean isDouble(double value) {
                      if (value % 1 == 0) {
                          Log.d(TAG, "value is " + value + " and is not double");
                          return false;
                      } else {
                          Log.d(TAG, "value is " + value + " and is double");
                          return true;
                      }
                  }
              

              上面的方法只是简单地检查值是否有零作为十进制数字。

              private String formatFileSize(long size) {
                      String hrSize = null;
                      double b = size;
                      double k = size/1024.0;
                      double m = ((size/1024.0)/1024.0);
                      double g = (((size/1024.0)/1024.0)/1024.0);
                      double t = ((((size/1024.0)/1024.0)/1024.0)/1024.0);
              
                      DecimalFormat dec1 = new DecimalFormat("0.00");
                      DecimalFormat dec2 = new DecimalFormat("0");
                      if (t>1) {
                          hrSize = isDouble(t) ? dec1.format(t).concat(" TB") : dec2.format(t).concat(" TB");
                      } else if (g>1) {
                          hrSize = isDouble(g) ? dec1.format(g).concat(" GB") : dec2.format(g).concat(" GB");
                      } else if (m>1) {
                          hrSize = isDouble(m) ? dec1.format(m).concat(" MB") : dec2.format(m).concat(" MB");
                      } else if (k>1) {
                          hrSize = isDouble(k) ? dec1.format(k).concat(" KB") : dec2.format(k).concat(" KB");
                      } else {
                          hrSize = isDouble(b) ? dec1.format(b).concat(" B") : dec2.format(b).concat(" B");
                      }
                      return hrSize;
                  }
              

              【讨论】:

                猜你喜欢
                • 2012-08-02
                • 2015-05-18
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多