Làm cách nào để chuyển đổi kích thước byte thành định dạng có thể đọc được trong Java?


556

Làm cách nào để chuyển đổi kích thước byte thành định dạng có thể đọc được trong Java? Giống như 1024 sẽ trở thành "1 Kb" và 1024 * 1024 sẽ trở thành "1 Mb".

Tôi phát ngán với việc viết phương pháp tiện ích này cho từng dự án. Có phương thức tĩnh nào trong Apache Commons cho việc này không?


32
Nếu bạn sử dụng các đơn vị được tiêu chuẩn hóa, 1024 sẽ trở thành "1KiB" và 1024 * 1024 sẽ trở thành "1MiB". vi.wikipedia.org/wiki/Binary_prefix
Pascal Cuoq

@Pascal: Cần có một số chức năng hoặc một tùy chọn để chỉ định cơ sở và đơn vị.
Aaron Digulla


3
@Pascal Cuoq: Cảm ơn bạn đã tham khảo. Tôi đã không nhận ra cho đến khi tôi đọc được rằng ở đây tại EU, chúng tôi bắt buộc phải sử dụng các tiền tố chính xác theo luật.
JeremyP

2
@DerMike Bạn đã đề cập rằng "Cho đến khi một thư viện như vậy tồn tại". Điều này giờ đã trở thành sự thật. :-) stackoverflow.com/questions/3758606/ từ
Christian Esken

Câu trả lời:


1310

Sự thật thú vị: Đoạn mã gốc được đăng ở đây là đoạn mã Java được sao chép nhiều nhất mọi thời đại trên Stack Overflow và nó đã bị lỗi. Nó đã được sửa nhưng nó trở nên lộn xộn.

Câu chuyện đầy đủ trong bài viết này: Đoạn trích StackOverflow được sao chép nhiều nhất mọi thời đại là thiếu sót!

Nguồn: Định dạng kích thước byte thành định dạng có thể đọc được của con người | Lập trình.

SI (1 k = 1.000)

public static String humanReadableByteCountSI(long bytes) {
    if (-1000 < bytes && bytes < 1000) {
        return bytes + " B";
    }
    CharacterIterator ci = new StringCharacterIterator("kMGTPE");
    while (bytes <= -999_950 || bytes >= 999_950) {
        bytes /= 1000;
        ci.next();
    }
    return String.format("%.1f %cB", bytes / 1000.0, ci.current());
}

Nhị phân (1 K = 1.024)

public static String humanReadableByteCountBin(long bytes) {
    long absB = bytes == Long.MIN_VALUE ? Long.MAX_VALUE : Math.abs(bytes);
    if (absB < 1024) {
        return bytes + " B";
    }
    long value = absB;
    CharacterIterator ci = new StringCharacterIterator("KMGTPE");
    for (int i = 40; i >= 0 && absB > 0xfffccccccccccccL >> i; i -= 10) {
        value >>= 10;
        ci.next();
    }
    value *= Long.signum(bytes);
    return String.format("%.1f %ciB", value / 1024.0, ci.current());
}

Ví dụ đầu ra:

                              SI     BINARY

                   0:        0 B        0 B
                  27:       27 B       27 B
                 999:      999 B      999 B
                1000:     1.0 kB     1000 B
                1023:     1.0 kB     1023 B
                1024:     1.0 kB    1.0 KiB
                1728:     1.7 kB    1.7 KiB
              110592:   110.6 kB  108.0 KiB
             7077888:     7.1 MB    6.8 MiB
           452984832:   453.0 MB  432.0 MiB
         28991029248:    29.0 GB   27.0 GiB
       1855425871872:     1.9 TB    1.7 TiB
 9223372036854775807:     9.2 EB    8.0 EiB   (Long.MAX_VALUE)

12
Tôi thích 1.0 KB. Sau đó, rõ ràng có bao nhiêu con số đáng kể đầu ra đòi hỏi. (Đây dường như cũng là hành vi của dulệnh trong Linux.)
aioobe

19
Tôi nghĩ rằng mọi người nên lưu ý rằng trong dự án của bạn, khách hàng muốn thấy các giá trị trong cơ sở 2 (được chia theo 1024) nhưng với tiền tố chung. Không phải KiB, MiB, GiB, v.v ... Sử dụng KB, MB, GB, TB cho nó.
Borys

27
@Borys Sử dụng "KB" có nghĩa là "1024 byte" là sai. Đừng làm vậy.
endolith

8
Người đọc sẽ tìm hiểu nó. Tốt hơn là một cái gì đó họ không quen thuộc và có thể tìm hiểu nó hơn là có một cái gì đó sai. Viết KB một người dùng quen thuộc với nó sẽ mong đợi 1000 và một người dùng không quen thuộc sẽ mong đợi 1024.
kap

16
Trả lời viết lại hoàn toàn. Nhiều ý kiến ​​trên đã lỗi thời.
aioobe

305

FileUtils.byteCountToDisplaySize(long size)sẽ làm việc nếu dự án của bạn có thể phụ thuộc vào org.apache.commons.io.

JavaDoc cho phương thức này


18
Tôi đã có commons-io trong dự án của mình, nhưng cuối cùng lại sử dụng mã của aioobe, vì hành vi làm tròn (xem liên kết cho JavaDoc)
Iravanchi

3
Có một tiện ích để làm các hoạt động ngược lại. Lấy số byte từ số byte có thể đọc được của con người?
arunmoezhi

6
Thật không may, chức năng này không nhận thức được địa phương; trong tiếng Pháp, ví dụ, họ luôn gọi byte là "octet", vì vậy nếu bạn sẽ hiển thị tệp 100 KB cho người dùng Pháp, nhãn chính xác sẽ là 100 Ko.
Tacroy

@Tacroy Bạn có thể nhận đầu ra octet với UnitFormatter trong thư viện triava. Bạn có thể vượt qua bất kỳ đơn vị nào cho byte, Watts hoặc octet. Ví dụ, được sửa đổi một chút từ các ví dụ trong github.com/trivago/triava : UnitFormatter.formatAsUnit (1126, UnitSystem.SI, "o"); // = "1.13 ko" Thêm ví dụ trong: stackoverflow.com/questions/3758606/
Kẻ

5
vòng này đến gb gần nhất khi> 1 gb, điều đó có nghĩa là độ chính xác bạn nhận được từ nó thay đổi
tksfz

180

Sử dụng Lớp dựng sẵn của Android

Đối với Android có một lớp Formatter . Chỉ cần một dòng mã và bạn đã hoàn thành.

android.text.format.Formatter.formatShortFileSize(activityContext, bytes);

Nó giống như formatFileSize(), nhưng cố gắng tạo ra các số ngắn hơn (hiển thị số thập phân ít hơn).

android.text.format.Formatter.formatFileSize(activityContext, bytes);

Định dạng kích thước nội dung ở dạng byte, kilobyte, megabyte, v.v.


12
nên là câu trả lời tốt nhất cho ANDROID dứt khoát. Không cần thêm thư viện. +1
ăn kiêng

11
Tôi ghét thực tế bạn phải vượt qua Context.
Jared Burrows

4
Nên là câu trả lời tốt nhất cho ANDROID dứt khoát.
shridutt kothari

5
Bạn vượt qua trong Ngữ cảnh để nó được dịch sang Địa điểm hiện tại của người dùng. Nếu không, nó sẽ không phải là một chức năng rất hữu ích.
phreakhead

7
Tôi đã sử dụng câu trả lời được chấp nhận trước khi tôi biết điều này. Chỉ cần lưu ý, trong Build.VERSION_CODES.N và trước đó, quyền hạn 1024 được sử dụng thay thế, với KB = 1024 byte, MB = 1.048.576 byte, v.v. Kể từ O, các tiền tố được sử dụng theo nghĩa chuẩn của chúng trong hệ thống SI , vì vậy kB = 1000 byte, MB = 1.000.000 byte, v.v.
HendraWD

57

Chúng ta hoàn toàn có thể tránh sử dụng phương thức chậm Math.pow()Math.log()phương thức mà không hy sinh tính đơn giản vì hệ số giữa các đơn vị (ví dụ B, KB, MB, v.v.) là 1024, là 2 ^ 10. Các Longlớp học có một tiện dụng numberOfLeadingZeros()phương pháp mà chúng tôi có thể sử dụng để cho các đơn vị giá trị kích thước rơi vào.

Điểm chính: Đơn vị kích thước có khoảng cách 10 bit (1024 = 2 ^ 10) có nghĩa là vị trí của 1 bit cao nhất - hay nói cách khác, số lượng các số 0 đứng đầu - khác nhau 10 (Byte = KB * 1024, KB = MB * 1024, v.v.).

Tương quan giữa số lượng số 0 hàng đầu và đơn vị kích thước:

# of leading 0's   Size unit
-------------------------------
>53                B (Bytes)
>43                KB
>33                MB
>23                GB
>13                TB
>3                 PB
<=2                EB

Mã cuối cùng:

public static String formatSize(long v) {
    if (v < 1024) return v + " B";
    int z = (63 - Long.numberOfLeadingZeros(v)) / 10;
    return String.format("%.1f %sB", (double)v / (1L << (z*10)), " KMGTPE".charAt(z));
}

24

Tôi đã hỏi cùng một câu hỏi gần đây:

Định dạng kích thước tệp như MB, GB, v.v.

Mặc dù không có câu trả lời ngoài lề, tôi có thể sống với giải pháp:

private static final long K = 1024;
private static final long M = K * K;
private static final long G = M * K;
private static final long T = G * K;

public static String convertToStringRepresentation(final long value){
    final long[] dividers = new long[] { T, G, M, K, 1 };
    final String[] units = new String[] { "TB", "GB", "MB", "KB", "B" };
    if(value < 1)
        throw new IllegalArgumentException("Invalid file size: " + value);
    String result = null;
    for(int i = 0; i < dividers.length; i++){
        final long divider = dividers[i];
        if(value >= divider){
            result = format(value, divider, units[i]);
            break;
        }
    }
    return result;
}

private static String format(final long value,
    final long divider,
    final String unit){
    final double result =
        divider > 1 ? (double) value / (double) divider : (double) value;
    return new DecimalFormat("#,##0.#").format(result) + " " + unit;
}

Mã kiểm tra:

public static void main(final String[] args){
    final long[] l = new long[] { 1l, 4343l, 43434334l, 3563543743l };
    for(final long ll : l){
        System.out.println(convertToStringRepresentation(ll));
    }
}

Đầu ra (trên Địa điểm tiếng Đức của tôi):

1 B
4,2 KB
41,4 MB
3,3 GB

Chỉnh sửa: Tôi đã mở một Vấn đề yêu cầu chức năng này cho Google Guava . Có lẽ ai đó sẽ quan tâm để hỗ trợ nó.


2
Tại sao 0 có kích thước tệp không hợp lệ?
aioobe

@aioobe đó là trong trường hợp sử dụng của tôi (hiển thị kích thước của tệp được tải lên), nhưng có thể cho rằng đó không phải là phổ biến
Sean Patrick Floyd

Nếu bạn thay đổi dòng cuối cùng để trả về NumberFormat.getFormat ("#, ## 0. #"). Định dạng (kết quả) + "" + đơn vị; nó cũng hoạt động trong GWT! Cảm ơn vì điều này, nó vẫn không ở ổi.
tom

9

Đây là phiên bản sửa đổi của câu trả lời của aioobe .

Thay đổi:

  • Localetham số, bởi vì một số ngôn ngữ sử dụng .và những ngôn ngữ khác ,là dấu thập phân.
  • mã người có thể đọc được

private static final String[] SI_UNITS = { "B", "kB", "MB", "GB", "TB", "PB", "EB" };
private static final String[] BINARY_UNITS = { "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB" };

public static String humanReadableByteCount(final long bytes, final boolean useSIUnits, final Locale locale)
{
    final String[] units = useSIUnits ? SI_UNITS : BINARY_UNITS;
    final int base = useSIUnits ? 1000 : 1024;

    // When using the smallest unit no decimal point is needed, because it's the exact number.
    if (bytes < base) {
        return bytes + " " + units[0];
    }

    final int exponent = (int) (Math.log(bytes) / Math.log(base));
    final String unit = units[exponent];
    return String.format(locale, "%.1f %s", bytes / Math.pow(base, exponent), unit);
}

Đó là một kết quả hỗn hợp một chút khi truyền cùng một tham số Locale chỉ cho các ký hiệu phân tách, nhưng sau đó cũng không bản địa hóa đơn vị để tính các ngôn ngữ cũng sử dụng một ký hiệu khác cho Byte, như tiếng Pháp.
Nzall

@Nzall Ý bạn là octet? Wikipedia nói rằng nó không còn phổ biến nữa. Khác, bạn có một tài liệu tham khảo?
Christian Strempfer

7

Nếu bạn sử dụng Android, bạn chỉ cần sử dụng android.text.format.Formatter.formatFileSize () .

Thay thế, đây là một giải pháp dựa trên bài đăng phổ biến này :

  /**
   * formats the bytes to a human readable format
   *
   * @param si true if each kilo==1000, false if kilo==1024
   */
  @SuppressLint("DefaultLocale")
  public static String humanReadableByteCount(final long bytes,final boolean si)
    {
    final int unit=si ? 1000 : 1024;
    if(bytes<unit)
      return bytes+" B";
    double result=bytes;
    final String unitsToUse=(si ? "k" : "K")+"MGTPE";
    int i=0;
    final int unitsCount=unitsToUse.length();
    while(true)
      {
      result/=unit;
      if(result<unit)
        break;
      // check if we can go further:
      if(i==unitsCount-1)
        break;
      ++i;
      }
    final StringBuilder sb=new StringBuilder(9);
    sb.append(String.format("%.1f ",result));
    sb.append(unitsToUse.charAt(i));
    if(si)
      sb.append('B');
    else sb.append('i').append('B');
    final String resultStr=sb.toString();
    return resultStr;
    }

Hoặc trong Kotlin:

/**
 * formats the bytes to a human readable format
 *
 * @param si true if each kilo==1000, false if kilo==1024
 */
@SuppressLint("DefaultLocale")
fun humanReadableByteCount(bytes: Long, si: Boolean): String? {
    val unit = if (si) 1000.0 else 1024.0
    if (bytes < unit)
        return "$bytes B"
    var result = bytes.toDouble()
    val unitsToUse = (if (si) "k" else "K") + "MGTPE"
    var i = 0
    val unitsCount = unitsToUse.length
    while (true) {
        result /= unit
        if (result < unit || i == unitsCount - 1)
            break
        ++i
    }
    return with(StringBuilder(9)) {
        append(String.format("%.1f ", result))
        append(unitsToUse[i])
        if (si) append('B') else append("iB")
    }.toString()
}

Bạn dường như có một lỗi trong vòng lặp for của bạn. Tôi nghĩ rằng nó nên unitsCountvà không unitsCount-1.
aioobe

@aioobe nhưng điều này có nghĩa là vòng lặp có thể dừng khi i == unitsCount, có nghĩa là i == 6, có nghĩa là "charAt" sẽ thất bại ...
nhà phát triển Android

if(result<unit) break;sẽ đá vào trước đó. Đừng lo lắng. (Nếu bạn kiểm tra nó, bạn sẽ nhận thấy rằng bạn có thể bỏ qua hoàn toàn điều kiện vòng lặp.)
aioobe

@aioobe Đúng, đó là do giả định (đúng) mà tôi xử lý loại biến "dài". Ngoài ra, nó dựa trên giả định rằng các đơn vị sẽ ít nhất là những gì tôi đã viết. Nếu bạn sử dụng ít đơn vị hơn, nó sẽ tạo ra kết quả kỳ lạ (sẽ thích các giá trị nhỏ hơn 1, hơn là các giá trị lớn hơn 1000).
nhà phát triển Android

@aioobe Đúng. Tôi sẽ sửa nó. BTW, thuật toán của bạn cũng có thể cung cấp một kết quả kỳ lạ. hãy thử đưa ra "999999, đúng" làm đối số. nó sẽ hiển thị "1000.0 kB", vì vậy nó được làm tròn, nhưng khi mọi người nhìn thấy nó, họ có thể tự hỏi: tại sao nó không thể hiển thị 1MB, vì 1000KB = 1MB ... Bạn nghĩ điều này nên được xử lý như thế nào? Đó là vì String.format, nhưng tôi không chắc nó nên được sửa như thế nào.
nhà phát triển Android

6

private static final String[] Q = new String[]{"", "K", "M", "G", "T", "P", "E"};

public String getAsString(long bytes)
{
    for (int i = 6; i > 0; i--)
    {
        double step = Math.pow(1024, i);
        if (bytes > step) return String.format("%3.1f %s", bytes / step, Q[i]);
    }
    return Long.toString(bytes);
}

6
  private String bytesIntoHumanReadable(long bytes) {
        long kilobyte = 1024;
        long megabyte = kilobyte * 1024;
        long gigabyte = megabyte * 1024;
        long terabyte = gigabyte * 1024;

        if ((bytes >= 0) && (bytes < kilobyte)) {
            return bytes + " B";

        } else if ((bytes >= kilobyte) && (bytes < megabyte)) {
            return (bytes / kilobyte) + " KB";

        } else if ((bytes >= megabyte) && (bytes < gigabyte)) {
            return (bytes / megabyte) + " MB";

        } else if ((bytes >= gigabyte) && (bytes < terabyte)) {
            return (bytes / gigabyte) + " GB";

        } else if (bytes >= terabyte) {
            return (bytes / terabyte) + " TB";

        } else {
            return bytes + " Bytes";
        }
    }

Tôi thích điều này bởi vì nó dễ làm theo và dễ hiểu.
Joshua Pinter

6

Đơn vị Byte cho phép bạn làm điều đó như thế này:

long input1 = 1024;
long input2 = 1024 * 1024;

Assert.assertEquals("1 KiB", BinaryByteUnit.format(input1));
Assert.assertEquals("1 MiB", BinaryByteUnit.format(input2));

Assert.assertEquals("1.024 KB", DecimalByteUnit.format(input1, "#.0"));
Assert.assertEquals("1.049 MB", DecimalByteUnit.format(input2, "#.000"));

NumberFormat format = new DecimalFormat("#.#");
Assert.assertEquals("1 KiB", BinaryByteUnit.format(input1, format));
Assert.assertEquals("1 MiB", BinaryByteUnit.format(input2, format));

Tôi đã viết một thư viện khác gọi là bộ lưu trữ cho phép bạn làm như thế này:

String formattedUnit1 = StorageUnits.formatAsCommonUnit(input1, "#");
String formattedUnit2 = StorageUnits.formatAsCommonUnit(input2, "#");
String formattedUnit3 = StorageUnits.formatAsBinaryUnit(input1);
String formattedUnit4 = StorageUnits.formatAsBinaryUnit(input2);
String formattedUnit5 = StorageUnits.formatAsDecimalUnit(input1, "#.00", Locale.GERMAN);
String formattedUnit6 = StorageUnits.formatAsDecimalUnit(input2, "#.00", Locale.GERMAN);
String formattedUnit7 = StorageUnits.formatAsBinaryUnit(input1, format);
String formattedUnit8 = StorageUnits.formatAsBinaryUnit(input2, format);

Assert.assertEquals("1 kB", formattedUnit1);
Assert.assertEquals("1 MB", formattedUnit2);
Assert.assertEquals("1.00 KiB", formattedUnit3);
Assert.assertEquals("1.00 MiB", formattedUnit4);
Assert.assertEquals("1,02 kB", formattedUnit5);
Assert.assertEquals("1,05 MB", formattedUnit6);
Assert.assertEquals("1 KiB", formattedUnit7);
Assert.assertEquals("1 MiB", formattedUnit8);

Trong trường hợp bạn muốn buộc một đơn vị nhất định, hãy làm điều này:

String formattedUnit9 = StorageUnits.formatAsKibibyte(input2);
String formattedUnit10 = StorageUnits.formatAsCommonMegabyte(input2);

Assert.assertEquals("1024.00 KiB", formattedUnit9);
Assert.assertEquals("1.00 MB", formattedUnit10);

5
    public static String floatForm (double d)
    {
       return new DecimalFormat("#.##").format(d);
    }


    public static String bytesToHuman (long size)
    {
        long Kb = 1  * 1024;
        long Mb = Kb * 1024;
        long Gb = Mb * 1024;
        long Tb = Gb * 1024;
        long Pb = Tb * 1024;
        long Eb = Pb * 1024;

        if (size <  Kb)                 return floatForm(        size     ) + " byte";
        if (size >= Kb && size < Mb)    return floatForm((double)size / Kb) + " Kb";
        if (size >= Mb && size < Gb)    return floatForm((double)size / Mb) + " Mb";
        if (size >= Gb && size < Tb)    return floatForm((double)size / Gb) + " Gb";
        if (size >= Tb && size < Pb)    return floatForm((double)size / Tb) + " Tb";
        if (size >= Pb && size < Eb)    return floatForm((double)size / Pb) + " Pb";
        if (size >= Eb)                 return floatForm((double)size / Eb) + " Eb";

        return "???";
    }

3

Hiện tại có một thư viện có chứa định dạng đơn vị. Tôi đã thêm nó vào bộ ba thư viện , vì chỉ có thư viện hiện có khác là dành cho Android.

Nó có thể định dạng số với độ chính xác tùy ý, trong 3 hệ thống khác nhau (SI, IEC, JEDEC) và các tùy chọn đầu ra khác nhau. Dưới đây là một số ví dụ mã từ các bài kiểm tra đơn vị triava :

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

In chính xác kilo, giá trị mega (ở đây với W = Watt):

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

Bạn có thể vượt qua DecimalFormat để tùy chỉnh đầu ra:

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

Đối với các hoạt động tùy ý trên các giá trị kilo hoặc mega, bạn có thể chia chúng thành các thành phần:

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

2

Tôi biết đã quá muộn để cập nhật bài viết này! nhưng tôi đã có một số niềm vui với điều này:

Tạo giao diện:

public interface IUnits {
     public String format(long size, String pattern);
     public long getUnitSize();
}

Tạo lớp StorageUnits:

import java.text.DecimalFormat;

public class StorageUnits {
private static final long K = 1024;
private static final long M = K * K;
private static final long G = M * K;
private static final long T = G * K;

enum Unit implements IUnits {
    TERA_BYTE {
        @Override
        public String format(long size, String pattern) {
            return format(size, getUnitSize(), "TB", pattern);
        }
        @Override
        public long getUnitSize() {
            return T;
        }
        @Override
        public String toString() {
            return "Terabytes";
        }
    },
    GIGA_BYTE {
        @Override
        public String format(long size, String pattern) {
            return format(size, getUnitSize(), "GB", pattern);
        }
        @Override
        public long getUnitSize() {
            return G;
        }
        @Override
        public String toString() {
            return "Gigabytes";
        }
    },
    MEGA_BYTE {
        @Override
        public String format(long size, String pattern) {
            return format(size, getUnitSize(), "MB", pattern);
        }
        @Override
        public long getUnitSize() {
            return M;
        }
        @Override
        public String toString() {
            return "Megabytes";
        }
    },
    KILO_BYTE {
        @Override
        public String format(long size, String pattern) {
            return format(size, getUnitSize(), "kB", pattern);
        }
        @Override
        public long getUnitSize() {
            return K;
        }
        @Override
        public String toString() {
            return "Kilobytes";
        }

    };
    String format(long size, long base, String unit, String pattern) {
        return new DecimalFormat(pattern).format(
                Long.valueOf(size).doubleValue() / Long.valueOf(base).doubleValue()
        ) + unit;
    }
}

public static String format(long size, String pattern) {
    for(Unit unit : Unit.values()) {
        if(size >= unit.getUnitSize()) {
            return unit.format(size, pattern);
        }
    }
    return ("???(" + size + ")???");
}

public static String format(long size) {
    return format(size, "#,##0.#");
}
}

Gọi nó đi:

class Main {
    public static void main(String... args) {
         System.out.println(StorageUnits.format(21885));
         System.out.println(StorageUnits.format(2188121545L));
    }
}

Đầu ra:

21.4kB
2GB

2

Trong trường hợp không may, nó sẽ tiết kiệm cho ai đó một chút thời gian, hoặc có thể chỉ để vui một chút, đây là phiên bản Go. Để đơn giản, tôi chỉ bao gồm trường hợp đầu ra nhị phân.

func sizeOf(bytes int64) string {
    const unit = 1024
    if bytes < unit {
        return fmt.Sprintf("%d B", bytes)
    }

    fb := float64(bytes)
    exp := int(math.Log(fb) / math.Log(unit))
    pre := "KMGTPE"[exp-1]
    div := math.Pow(unit, float64(exp))
    return fmt.Sprintf("%.1f %ciB", fb / div, pre)
}

1
String[] fileSizeUnits = {"bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"};
public String calculateProperFileSize(double bytes){
    String sizeToReturn = "";
    int index = 0;
    for(index = 0; index < fileSizeUnits.length; index++){
        if(bytes < 1024){
            break;
        }
        bytes = bytes / 1024;
    }

Chỉ cần thêm nhiều đơn vị tệp (nếu thiếu) và bạn sẽ thấy kích thước đơn vị tối đa cho đơn vị đó (nếu tệp của bạn có độ dài đó) System.out.println ("Kích thước tệp ở định dạng phù hợp:" + byte + "" + fileSizeUnits [mục lục]); sizeToReturn = String.valueOf (byte) + "" + fileSizeUnits [index]; trả về sizeToReturn; }


1

Đây là C # .net tương đương với câu trả lời đồng thuận chính xác của Java ở trên. (có một cái khác bên dưới có mã ngắn hơn)

    public static String BytesNumberToHumanReadableString(long bytes, bool SI1000orBinary1024)
    {

        int unit = SI1000orBinary1024 ? 1000 : 1024;
        if (bytes < unit) return bytes + " B";
        int exp = (int)(Math.Log(bytes) / Math.Log(unit));
        String pre = (SI1000orBinary1024 ? "kMGTPE" : "KMGTPE")[(exp - 1)] + (SI1000orBinary1024 ? "" : "i");
        return String.Format("{0:F1} {1}B", bytes / Math.Pow(unit, exp), pre);
    }

Về mặt kỹ thuật, nếu chúng ta sử dụng các đơn vị SI, thì thói quen này hoạt động đối với bất kỳ việc sử dụng số thường xuyên. Có nhiều câu trả lời tốt khác từ các chuyên gia. Giả sử bạn đang thực hiện cơ sở dữ liệu các con số trên lưới xem, giá trị của nó để kiểm tra các thói quen được tối ưu hóa hiệu suất từ ​​chúng.

PS: Đăng bởi vì câu hỏi / câu trả lời này xuất hiện trên đầu trang tìm kiếm google trong khi tôi đang làm dự án C #.


1

Bạn có thể sử dụng StringUtils xông s TraditionalBinarPrefix:

public static String humanReadableInt(long number) {
    return TraditionalBinaryPrefix.long2String(number,””,1);
}

1

hơi cũ nhưng, ... org.springframework.util.unit.DataSize có thể phù hợp với yêu cầu này ít nhất là để tính toán, sau đó một người trang trí đơn giản sẽ làm


0
filename=filedilg.getSelectedFile().getAbsolutePath();
File file=new File(filename);

String disp=FileUtils.byteCountToDisplaySize(file.length());
System.out.println("THE FILE PATH IS "+file+"THIS File SIZE IS IN MB "+disp);

Câu trả lời này, trong khi nó hoạt động, là phần bổ sung cho câu trả lời trước trong chủ đề này bởi @ user601806: stackoverflow.com/a/4888400/3987745 Để câu trả lời này hoạt động, bạn cần Apache Commons IO ( commons.apache.org/proper/ commons-io ) phụ thuộc.
Edward Quixote

0

Bạn đã thử JSR 363 chưa? Các mô-đun mở rộng đơn vị của nó như Unicode CLDR (trong GitHub: uom-system ) làm tất cả những điều đó cho bạn.

Bạn có thể sử dụng MetricPrefixbao gồm trong mọi triển khai hoặc BinaryPrefix(có thể so sánh với một số ví dụ ở trên) và nếu bạn sống và làm việc ở Ấn Độ hoặc một quốc gia lân cận, IndianPrefix(cũng trong mô-đun chung của hệ thống uom) cho phép bạn sử dụng và định dạng "Crore Byte "hoặc" Lakh Byte ", quá.


0

Có lẽ bạn có thể sử dụng mã này (trong C #):

        long Kb = 1024;
        long Mb = Kb * 1024;
        long Gb = Mb * 1024;
        long Tb = Gb * 1024;
        long Pb = Tb * 1024;
        long Eb = Pb * 1024;

        if (size < Kb) return size.ToString() + " byte";
        if (size < Mb) return (size / Kb).ToString("###.##") + " Kb.";
        if (size < Gb) return (size / Mb).ToString("###.##") + " Mb.";
        if (size < Tb) return (size / Gb).ToString("###.##") + " Gb.";
        if (size < Pb) return (size / Tb).ToString("###.##") + " Tb.";
        if (size < Eb) return (size / Pb).ToString("###.##") + " Pb.";
        if (size >= Eb) return (size / Eb).ToString("###.##") + " Eb.";

        return "invalid size";

0
public String humanReadable(long size) {
    long limit = 10 * 1024;
    long limit2 = limit * 2 - 1;
    String negative = "";
    if(size < 0) {
        negative = "-";
        size = Math.abs(size);
    }

    if(size < limit) {
        return String.format("%s%s bytes", negative, size);
    } else {
        size = Math.round((double) size / 1024);
        if (size < limit2) {
            return String.format("%s%s kB", negative, size);
        } else {
            size = Math.round((double)size / 1024);
            if (size < limit2) {
                return String.format("%s%s MB", negative, size);
            } else {
                size = Math.round((double)size / 1024);
                if (size < limit2) {
                    return String.format("%s%s GB", negative, size);
                } else {
                    size = Math.round((double)size / 1024);
                        return String.format("%s%s TB", negative, size);
                }
            }
        }
    }
}

0

Sử dụng chức năng sau để có được thông tin chính xác, Được tạo bằng cách lấy cơ sở của ATM_CashWithdrawlkhái niệm.

getFullMemoryUnit(): Total: [123 MB], Max: [1 GB, 773 MB, 512 KB], Free: [120 MB, 409 KB, 304 Bytes]
public static String getFullMemoryUnit(long unit) {
    long BYTE = 1024, KB = BYTE, MB = KB * KB, GB = MB * KB, TB = GB * KB;
    long KILO_BYTE, MEGA_BYTE = 0, GIGA_BYTE = 0, TERA_BYTE = 0;
    unit = Math.abs(unit);
    StringBuffer buffer = new StringBuffer();
    if ( unit / TB > 0 ) {
        TERA_BYTE = (int) (unit / TB);
        buffer.append(TERA_BYTE+" TB");
        unit -= TERA_BYTE * TB;
    }
    if ( unit / GB > 0 ) {
        GIGA_BYTE = (int) (unit / GB);
        if (TERA_BYTE != 0) buffer.append(", ");
        buffer.append(GIGA_BYTE+" GB");
        unit %= GB;
    }
    if ( unit / MB > 0 ) {
        MEGA_BYTE = (int) (unit / MB);
        if (GIGA_BYTE != 0) buffer.append(", ");
        buffer.append(MEGA_BYTE+" MB");
        unit %= MB;
    }
    if ( unit / KB > 0 ) {
        KILO_BYTE = (int) (unit / KB);
        if (MEGA_BYTE != 0) buffer.append(", ");
        buffer.append(KILO_BYTE+" KB");
        unit %= KB;
    }
    if ( unit > 0 ) buffer.append(", "+unit+" Bytes");
    return buffer.toString();
}

Tôi vừa sửa đổi mã của facebookarchive-StringUtils để có được định dạng dưới đây. Định dạng tương tự bạn sẽ nhận được khi bạn sử dụng apache.hadoop-StringUtils

getMemoryUnit(): Total: [123.0 MB], Max: [1.8 GB], Free: [120.4 MB]
public static String getMemoryUnit(long bytes) {
    DecimalFormat oneDecimal = new DecimalFormat("0.0");
    float BYTE = 1024.0f, KB = BYTE, MB = KB * KB, GB = MB * KB, TB = GB * KB;
    long absNumber = Math.abs(bytes);
    double result = bytes;
    String suffix = " Bytes";
    if (absNumber < MB) {
        result = bytes / KB;
        suffix = " KB";
    } else if (absNumber < GB) {
        result = bytes / MB;
        suffix = " MB";
    } else if (absNumber < TB) {
        result = bytes / GB;
        suffix = " GB";
    }
    return oneDecimal.format(result) + suffix;
}

Ví dụ sử dụng các phương pháp trên:

public static void main(String[] args) {
    Runtime runtime = Runtime.getRuntime();
    int availableProcessors = runtime.availableProcessors();

    long heapSize = Runtime.getRuntime().totalMemory(); 
    long heapMaxSize = Runtime.getRuntime().maxMemory();
    long heapFreeSize = Runtime.getRuntime().freeMemory();

    System.out.format("Total: [%s], Max: [%s], Free: [%s]\n", heapSize, heapMaxSize, heapFreeSize);
    System.out.format("getMemoryUnit(): Total: [%s], Max: [%s], Free: [%s]\n",
            getMemoryUnit(heapSize), getMemoryUnit(heapMaxSize), getMemoryUnit(heapFreeSize));
    System.out.format("getFullMemoryUnit(): Total: [%s], Max: [%s], Free: [%s]\n",
            getFullMemoryUnit(heapSize), getFullMemoryUnit(heapMaxSize), getFullMemoryUnit(heapFreeSize));
}

Byte để có được định dạng trên

Total: [128974848], Max: [1884815360], Free: [126248240]

Để hiển thị thời gian ở định dạng có thể đọc được, hãy sử dụng chức năng này millisToShortDHMS(long duration).


0

đây là chuyển đổi từ @aioobe được chuyển đổi sang kotlin

/**
 * https://stackoverflow.com/a/3758880/1006741
 */
fun Long.humanReadableByteCountBinary(): String {
    val b = when (this) {
        Long.MIN_VALUE -> Long.MAX_VALUE
        else -> abs(this)
    }
    return when {
        b < 1024L -> "$this B"
        b <= 0xfffccccccccccccL shr 40 -> "%.1f KiB".format(Locale.UK, this / 1024.0)
        b <= 0xfffccccccccccccL shr 30 -> "%.1f MiB".format(Locale.UK, this / 1048576.0)
        b <= 0xfffccccccccccccL shr 20 -> "%.1f GiB".format(Locale.UK, this / 1.073741824E9)
        b <= 0xfffccccccccccccL shr 10 -> "%.1f TiB".format(Locale.UK, this / 1.099511627776E12)
        b <= 0xfffccccccccccccL -> "%.1f PiB".format(Locale.UK, (this shr 10) / 1.099511627776E12)
        else -> "%.1f EiB".format(Locale.UK, (this shr 20) / 1.099511627776E12)
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.