Bagaimana cara mengubah ukuran byte menjadi format yang dapat dibaca manusia di Jawa?

556

Bagaimana cara mengubah ukuran byte menjadi format yang dapat dibaca manusia di Jawa? Seperti 1024 harus menjadi "1 Kb" dan 1024 * 1024 harus menjadi "1 Mb".

Saya agak bosan menulis metode utilitas ini untuk setiap proyek. Apakah ada metode statis di Apache Commons untuk ini?

Igor Mukhin
sumber
32
Jika Anda menggunakan unit standar, 1024 harus menjadi "1KiB" dan 1024 * 1024 harus menjadi "1MiB". en.wikipedia.org/wiki/Binary_prefix
Pascal Cuoq
@ Pascal: Harus ada beberapa fungsi atau opsi untuk menentukan basis dan unit.
Aaron Digulla
mungkin duplikat ukuran file Format sebagai MB, GB dll
Aaron Digulla
3
@ Pascal Cuoq: Terima kasih untuk referensi. Saya tidak menyadari sampai saya membacanya bahwa di sini di UE kita diharuskan untuk menggunakan awalan yang benar oleh hukum.
JeremyP
2
@DerMike Anda menyebutkan bahwa "Sampai perpustakaan seperti itu ada". Ini sekarang menjadi benar. :-) stackoverflow.com/questions/3758606/…
Christian Esken

Jawaban:

1310

Fakta menyenangkan: Cuplikan asli yang diposting di sini adalah cuplikan Java yang paling banyak disalin sepanjang masa di Stack Overflow, dan cacat. Itu diperbaiki tetapi menjadi berantakan.

Kisah lengkap dalam artikel ini: Cuplikan StackOverflow yang paling banyak disalin sepanjang masa adalah cacat!

Sumber: Memformat ukuran byte ke format yang dapat dibaca manusia | Pemrograman. Panduan

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

Biner (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());
}

Contoh output:

                              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)
aioobe
sumber
12
Saya lebih suka 1,0 KB. Maka sudah jelas berapa banyak angka penting yang disyaratkan output. (Tampaknya ini juga merupakan perilaku duperintah misalnya di Linux.)
aioobe
19
Saya pikir setiap orang harus mencatat bahwa dalam pelanggan proyek Anda ingin melihat nilai-nilai dalam basis 2 (dibagi 1024) tetapi dengan awalan umum. Bukan KiB, MiB, GiB dll. Gunakan KB, MB, GB, TB untuk itu.
Borys
27
@Borys Menggunakan "KB" berarti "1024 byte" salah. Jangan lakukan itu.
endolith
8
Pembaca akan mempelajarinya. Lebih baik sesuatu yang mereka tidak kenal dan bisa mempelajarinya daripada memiliki sesuatu yang salah. Menulis KB pengguna yang terbiasa dengan itu akan mengharapkan 1000 dan pengguna yang tidak terbiasa akan mengharapkan 1024.
kap
16
Jawabannya ditulis ulang seluruhnya. Banyak komentar di atas sudah usang.
aioobe
305

FileUtils.byteCountToDisplaySize(long size)akan bekerja jika proyek Anda dapat diandalkan org.apache.commons.io.

JavaDoc untuk metode ini

pengguna601806
sumber
18
Saya sudah memiliki commons-io pada proyek saya, tetapi akhirnya menggunakan kode aioobe, karena perilaku pembulatan (lihat tautan untuk
JavaDoc
3
apakah ada utilitas untuk melakukan operasi terbalik. Mendapatkan jumlah byte dari jumlah byte yang dapat dibaca manusia?
arunmoezhi
6
Sayangnya fungsi ini tidak sadar lokal; dalam bahasa Prancis, misalnya, mereka selalu memanggil byte "oktet" jadi jika Anda akan menampilkan file 100 KB ke pengguna Prancis label yang benar adalah 100 Ko.
Tacroy
@Tacroy Anda bisa mendapatkan output oktet dengan UnitFormatter di pustaka triava. Anda dapat melewati unit apa pun untuk byte, Watt, atau oktet. Contoh, sedikit dimodifikasi dari contoh di github.com/trivago/triava : UnitFormatter.formatAsUnit (1126, UnitSystem.SI, "o"); // = "1,13 ko" Contoh lainnya di: stackoverflow.com/questions/3758606/…
Christian Esken
5
putaran ini ke gb terdekat ketika> 1 gb, yang berarti bahwa ketepatan yang Anda dapatkan bervariasi
tksfz
180

Gunakan Android builtin Class

Untuk Android ada Formatter kelas . Hanya satu baris kode dan Anda selesai.

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

Itu seperti formatFileSize(), tetapi mencoba untuk menghasilkan angka yang lebih pendek (menunjukkan lebih sedikit desimal).

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

Memformat ukuran konten dalam bentuk byte, kilobyte, megabita, dll.

AZ_
sumber
12
harus menjadi jawaban terbaik untuk ANDROID secara definitif. Tidak diperlukan perpustakaan tambahan. +1
pelaku diet
11
Aku benci kenyataan bahwa kamu harus masuk Context.
Jared Burrows
4
Harus menjadi jawaban terbaik untuk ANDROID secara definitif.
shridutt kothari
5
Anda meneruskan dalam Konteks sehingga diterjemahkan ke Lokal pengguna saat ini. Kalau tidak, itu tidak akan menjadi fungsi yang sangat berguna.
phreakhead
7
Saya menggunakan jawaban yang diterima sebelum saya tahu ini. Hanya untuk dicatat, Dalam Build.VERSION_CODES.N dan sebelumnya, kekuatan 1024 digunakan sebagai gantinya, dengan KB = 1024 byte, MB = 1.048.576 byte, dll. Pada O, awalan digunakan dalam arti standarnya dalam sistem SI. , jadi kB = 1000 byte, MB = 1.000.000 byte, dll.
HendraWD
57

Kita dapat sepenuhnya menghindari penggunaan metode Math.pow()dan lambat Math.log()tanpa mengorbankan kesederhanaan karena faktor antara unit (misalnya B, KB, MB dll.) Adalah 1024 yaitu 2 ^ 10. The Longkelas memiliki berguna numberOfLeadingZeros()metode yang dapat kita gunakan untuk membedakan mana unit nilai ukuran jatuh.

Poin kunci: Ukuran unit memiliki jarak 10 bit (1024 = 2 ^ 10) yang berarti posisi 1 bit tertinggi - atau dengan kata lain jumlah nol di depan - berbeda dengan 10 (Bytes = KB * 1024, KB = MB * 1024 dll.).

Korelasi antara jumlah nol terdepan dan satuan ukuran:

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

Kode terakhir:

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));
}
icza
sumber
24

Saya menanyakan pertanyaan yang sama baru-baru ini:

Memformat ukuran file sebagai MB, GB, dll

Meskipun tidak ada jawaban di luar kotak, saya dapat hidup dengan solusinya:

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

Kode uji:

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

Output (pada Bahasa Jerman saya):

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

Sunting: Saya telah membuka Masalah yang meminta fungsi ini untuk Google Guava . Mungkin seseorang akan peduli untuk mendukungnya.

Sean Patrick Floyd
sumber
2
Mengapa 0 berukuran file tidak valid?
aioobe
@aioobe itu dalam kasus penggunaan saya (menampilkan ukuran file yang diunggah), tetapi bisa dibilang itu tidak universal
Sean Patrick Floyd
Jika Anda mengubah baris terakhir untuk mengembalikan format NumberFormat.getFormat ("#, ## 0. #"). (Hasil) + "" + unit; itu bekerja di GWT juga! Terima kasih untuk ini, masih belum di Jambu Biji.
tom
9

Ini adalah versi modifikasi dari jawaban aioobe .

Perubahan:

  • Localeparameter, karena beberapa bahasa menggunakan .dan lainnya ,sebagai titik desimal.
  • kode yang bisa dibaca manusia

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);
}
Christian Strempfer
sumber
Ini adalah hasil yang agak beragam untuk meneruskan parameter Lokal hanya untuk simbol pemisah, tetapi kemudian tidak juga melokalisasi unit untuk memperhitungkan bahasa yang juga menggunakan simbol yang berbeda untuk Bytes, seperti Perancis.
Nzall
@Nzall Apakah maksud Anda oktet? Wikipedia menyatakan bahwa itu sudah tidak umum lagi. Lain, apakah Anda punya referensi?
Christian Strempfer
7

Jika Anda menggunakan Android, Anda cukup menggunakan android.text.format.Formatter.formatFileSize () .

Alternatifnya, berikut ini solusi berdasarkan pos populer ini :

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

Atau di 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()
}
pengembang android
sumber
Anda tampaknya memiliki kesalahan satu per satu di for-loop Anda. Saya pikir itu harus unitsCountdan tidak unitsCount-1.
aioobe
@aioobe tetapi ini berarti perulangan dapat berhenti ketika saya == unitsCount, yang berarti saya == 6, yang berarti "karakter" akan gagal ...
pengembang android
if(result<unit) break;akan menendang sebelum itu. Jangan khawatir. (Jika Anda mengujinya, Anda akan melihat bahwa Anda dapat melewati kondisi for-loop sepenuhnya.)
aioobe
@aioobe Benar, itu karena asumsi (yang benar) bahwa saya menangani tipe variabel "panjang". Juga, ini didasarkan pada asumsi bahwa unit akan setidaknya seperti yang saya tulis. Jika Anda menggunakan lebih sedikit unit, itu akan menghasilkan hasil yang aneh (akan lebih suka nilai kurang dari 1, daripada nilai lebih besar dari 1.000).
pengembang android
@aioobe Benar. Saya akan memperbaikinya. BTW, algoritme Anda juga dapat memberikan hasil yang aneh. coba berikan "999999, true" sebagai argumen. ini akan menampilkan "1000.0 kB", jadi bulat, tetapi ketika orang melihatnya, mereka dapat bertanya-tanya: mengapa tidak dapat menampilkan 1MB, karena 1000KB = 1MB ... Bagaimana menurut Anda ini harus ditangani? Itu karena bentuk String.format, tapi saya tidak yakin bagaimana itu harus diperbaiki.
pengembang 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);
}
Lars Bohl
sumber
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";
        }
    }
Sujith Manjavana
sumber
Saya suka ini karena mudah diikuti dan mudah dimengerti.
Joshua Pinter
6

Byte Units memungkinkan Anda melakukannya seperti ini:

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

Saya telah menulis perpustakaan lain yang disebut unit penyimpanan yang memungkinkan Anda melakukannya seperti ini:

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

Jika Anda ingin memaksa unit tertentu, lakukan ini:

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

Assert.assertEquals("1024.00 KiB", formattedUnit9);
Assert.assertEquals("1.00 MB", formattedUnit10);
Sebastian Hoß
sumber
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 "???";
    }
XXX
sumber
3

Sekarang ada satu perpustakaan yang tersedia yang berisi pemformatan unit. Saya menambahkannya ke perpustakaan triava , karena satu-satunya perpustakaan lain yang ada tampaknya menjadi satu untuk Android.

Ini dapat memformat angka dengan presisi sewenang-wenang, dalam 3 sistem yang berbeda (SI, IEC, JEDEC) dan berbagai opsi keluaran. Berikut adalah beberapa contoh kode dari pengujian unit triava :

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

Mencetak tepat kilo, nilai mega (di sini dengan W = Watt):

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

Anda dapat melewati DecimalFormat untuk menyesuaikan output:

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

Untuk operasi sewenang-wenang pada nilai kilo atau mega, Anda dapat membaginya menjadi komponen:

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

Saya tahu sudah terlambat untuk memperbarui posting ini! tapi saya bersenang-senang dengan ini:

Buat antarmuka:

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

Buat kelas 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.#");
}
}

Sebut saja:

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

Keluaran:

21.4kB
2GB
Ahmad AlMughrabi
sumber
2

Kalau-kalau itu menghemat waktu, atau mungkin hanya untuk bersenang-senang, inilah versi Go. Untuk mempermudah, saya hanya menyertakan case output biner.

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)
}
Rick-777
sumber
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;
    }

Cukup tambahkan lebih banyak unit file (jika ada yang hilang), dan Anda akan melihat ukuran unit hingga unit itu (jika file Anda memiliki panjang sebanyak itu) System.out.println ("Ukuran file dalam format yang tepat:" + bytes + "" + fileSizeUnits [indeks]); sizeToReturn = String.valueOf (bytes) + "" + fileSizeUnits [index]; mengembalikan sizeToReturn; }

Vishwajit R. Shinde
sumber
1

Ini setara dengan C # .net untuk jawaban konsensus yang benar di atas Java. (ada lagi di bawah ini yang memiliki kode lebih pendek)

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

Secara teknis, jika kita tetap pada unit SI, rutin ini berfungsi untuk setiap penggunaan angka secara teratur. Ada banyak jawaban bagus lainnya dari para ahli. Misalkan Anda melakukan penyatuan data angka pada tampilan kisi, nilainya untuk memeriksa kinerja yang dioptimalkan dari mereka.

PS: Diposting karena pertanyaan / jawaban ini muncul paling atas di pencarian google saat saya sedang melakukan proyek C #.

Chan Fun Chiat
sumber
1

Anda dapat menggunakan StringUtils s’ TraditionalBinarPrefix:

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

agak tua tapi, ... org.springframework.util.unit.DataSize bisa cocok dengan persyaratan ini setidaknya untuk perhitungan, maka dekorator sederhana akan melakukan

Tama
sumber
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);
Mano Chella
sumber
Jawaban ini, meskipun berfungsi, adalah pelengkap jawaban sebelumnya di utas ini oleh @ user601806: stackoverflow.com/a/4888400/3987745 Agar jawaban ini berfungsi, Anda memerlukan Apache Commons IO ( commons.apache.org/proper/ commons-io ) ketergantungan.
Edward Quixote
0

Sudahkah Anda mencoba JSR 363 ? Modul ekstensi unitnya seperti Unicode CLDR (di GitHub: uom-systems ) melakukan semua itu untuk Anda.

Anda dapat menggunakan MetricPrefixtermasuk dalam setiap implementasi atau BinaryPrefix(sebanding dengan beberapa contoh di atas) dan jika Anda misalnya tinggal dan bekerja di India atau negara terdekat, IndianPrefix(juga dalam modul umum sistem-uom) memungkinkan Anda untuk menggunakan dan memformat "Crore Bytes "atau" Lakh Bytes "juga.

Werner Keil
sumber
0

Mungkin Anda bisa menggunakan kode ini (dalam 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";
Jacons Morais
sumber
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);
                }
            }
        }
    }
}
Samkov Max
sumber
0

Gunakan fungsi berikut untuk mendapatkan informasi yang tepat, Dihasilkan dengan mengambil basis ATM_CashWithdrawlkonsep.

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

Saya baru saja memodifikasi kode facebookarchive-StringUtils untuk mendapatkan format di bawah ini. Format yang sama Anda akan dapatkan ketika Anda menggunakan 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;
}

Contoh penggunaan metode di atas:

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

Bytes untuk mendapatkan format di atas

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

Untuk menampilkan waktu dalam format yang dapat dibaca manusia gunakan fungsi ini millisToShortDHMS(long duration).

Yash
sumber
0

di sini adalah konversi dari @aioobe dikonversi ke 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)
    }
}
Kibotu
sumber