动态转换KB为MB、GB、TB

19
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。
10个回答

45

修改版,仅调用一次格式。包括“字节”。

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(拍字节)、EB(艾字节)、ZB(泽字节)和YB(尧字节)。 - Bill'o

32

您在进行整数除法。因此,除法的结果也是整数。并且小数部分被截断。

so, 1245 / 1024 = 1

将你的分割方式更改为浮点数分割:-

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");
    }

您需要先与更高的单位进行比较,然后再移动到更低的单位。


2
@pedja:对于 mgt,请使用 else if 而不是仅使用 if,因为即使一个小文件可能是 0.00000000001 TB(大于零)。 - Greg Hewgill
1
@GregHewgill.. 啊!没注意到那个。 - Rohit Jain
1
@pedja.. 你应该使用1进行比较,而不是使用0。将所有的if语句改为k > 1g > 1,... - Rohit Jain
1
@pedja..请检查编辑后的帖子。您需要稍微修改一下if比较。 - Rohit Jain
1
嗯,有很多可能的方法来实现你想要的功能。听起来你最终收敛到了一个适合你的实现方式。 - Greg Hewgill
显示剩余6条评论

14

我喜欢这个:

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 报告:致命异常:java.lang.ArrayIndexOutOfBoundsException 长度=5;索引=319302040 - user924
“不安全”是什么意思?对于合理的数字,此函数是安全的,并且它按照问题中要求的目的正常工作(从B到TiB)。如果您需要更多的大小,请将“PiB”和“EiB”添加到数组中以测量Pebibyte和Exbibyte,直到9,223,372,036,854,775,807字节。对于更大的数字,该函数需要重新设计。无论如何,您打算如何修复它以使其更“安全”(无论这意味着什么)? - Sampisa

5
问题在于你正在使用整数除法。请将你的代码更改为:
double m = size/1024.0;
double g = size/1048576.0;
double t = size/1073741824.0;

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

4
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


3

您正在执行整数除法,即31/15将得到2,而不是2.几何。

只需在数字后附加Dd,表示它为双精度浮点数,您就可以得到正确的结果。

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

3

要做到这一点并不容易。Rohit Jain提到了整数操作。同时,四舍五入可能是一个问题,因为总是向下取整可能并不理想。我建议选择一个可用的解决方案,比如在triava库中。

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

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

2
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;
    }
}

只需添加更多文件单元(如果有缺失),您将看到单元大小增加到该单元(如果您的文件长度足够)


1
非常好的回答!谢谢Vishwajit。 - Deepak kaku
我有一个问题:2362232012这个数字以字节为单位相当于2.362232012千兆字节,但是当我传递这个字节数时,我收到了一个错误,指出整数太大了?有什么想法吗? - Inside 4ndroid
1
@Inside4ndroid,请将您的字节数量数据类型更改为“long”数据类型,这样就不会出现错误了。我正在编辑我的代码,并将方法参数从double更改为long类型。 - Vishwajit R. Shinde
单位应该是KiB,MiB等,直到EiB,因为使用long类型无法测量超过8 exbibytes(-1字节)的数据。 - Sampisa

0

我的基本版本(你可以定义一些常量而不是每次计算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?)";
}

0

bickster's answer 的效果还不错,但它的问题在于返回结果如 45.00 Bytes12.00 KB。在我看来,如果最后一位小数是零,应该将其删除。因此,你可以得到 45 B12 KB(注意,Bytes 已经改为 B。这只是为了统一性,因为我们有 KB、MB 等,而不是 Kilobytes、Megabytes 等)。

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;
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接