Java'da bayt boyutunu insan tarafından okunabilir formata nasıl dönüştürebilirim?


556

Java'da bayt boyutunu insan tarafından okunabilir formata nasıl dönüştürebilirim? 1024 gibi "1 Kb" ve 1024 * 1024 "1 Mb" olmalıdır.

Her proje için bu faydalı yöntemi yazmaktan bıktım. Bunun için Apache Commons'ta statik yöntemler var mı?


32
Standart birimler kullanırsanız, 1024 "1KiB" ve 1024 * 1024 "1MiB" olmalıdır. en.wikipedia.org/wiki/Binary_prefix
Pascal Cuoq

@Pascal: Baz üniteyi ve üniteyi belirtmek için birkaç fonksiyon veya bir seçenek olmalıdır.
Aaron Digulla


3
@Pascal Cuoq: Referans için teşekkürler. AB'de burada yasalarca doğru önekleri kullanmamız gerektiğini anlayana kadar fark etmemiştim.
JeremyP

2
@DerMike "Böyle bir kütüphane var olana kadar" dan bahsettiniz. Bu artık gerçek oldu. :-) stackoverflow.com/questions/3758606/…
Christian Esken

Yanıtlar:


1310

İlginç gerçek: Burada yayınlanan orijinal snippet, Stack Overflow'daki tüm zamanların en çok kopyalanan Java snippet'iydi ve kusurluydu. Düzeltildi ama dağınık oldu.

Bu makaledeki tüm hikaye: Tüm zamanların en çok kopyalanan StackOverflow snippet'i kusurlu!

Kaynak: Bayt boyutunu insan tarafından okunabilir biçime biçimlendirme | Programming.Guide

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

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

Örnek çıktı:

                              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
1.0 KB'ı tercih ederim. Sonra çıktının kaç önemli figür içerdiği açıktır. (Bu aynı zamanda duLinux'taki komutun davranışı gibi görünmektedir .)
aioobe 21:10

19
Herkesin proje müşterinizde taban 2'deki değerleri (1024 ile ayrılmış) ancak ortak önekle görmek istediğini düşünüyorum. KiB, MiB, GiB vb değil. KB, MB, GB, TB kullanın.
Borys

27
@Borys "1024 bayt" demek için "KB" kullanmak yanlış. Bunu yapma.
endolith

8
Okuyucular öğrenecek. Bilmedikleri ve yanlış öğrenebileceklerinden daha iyi bir şey öğrenebilirler. KB'ye aşina bir kullanıcı 1000 yazmayı ve aşina olmayan bir kullanıcı 1024
yazmayı

16
Cevap tamamen yeniden yazıldı. Yukarıdaki yorumların çoğu eski.
aioobe

305

FileUtils.byteCountToDisplaySize(long size)projeniz güvenebiliyorsa işe yarayacaktır org.apache.commons.io.

Bu yöntem için JavaDoc


18
Projemde zaten ortak var, ancak yuvarlama davranışı nedeniyle aioobe kodunu kullandım (JavaDoc bağlantısına bakın)
Iravanchi

3
ters işlemi yapmak için bir yardımcı program var. İnsan tarafından okunabilen bayt sayısından bayt sayısı alınıyor mu?
arunmoezhi

6
Ne yazık ki bu işlev yerel ayarlara duyarlı değildir; Örneğin, Fransızca'da, her zaman bayt "sekizli" olarak adlandırılırlar, bu nedenle bir Fransız kullanıcısına 100 KB'lik bir dosya görüntüleyecekseniz, doğru etiket 100 Ko olur.
Tacroy

@Tacroy Triava kitaplığındaki UnitFormatter ile sekizli çıktı alabilirsiniz. Bayt, Watt veya sekizli için herhangi bir birimi geçirebilirsiniz. Örnek, github.com/trivago/triava'daki örneklerden biraz değiştirilmiş : UnitFormatter.formatAsUnit (1126, UnitSystem.SI, "o"); // = "1.13 ko" Daha fazla örnek: stackoverflow.com/questions/3758606/…
Christian Esken

5
bu> 1 gb olduğunda en yakın
gb'ye yuvarlar

180

Android yerleşik Sınıfını kullanma

Android için bir sınıf Formatlayıcı var . Sadece bir satır kod ve bitirdiniz.

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

Bu formatFileSize(), ancak daha kısa sayılar üretmeye çalışmak (daha az ondalık sayı gösteren).

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

İçerik boyutunu bayt, kilobayt, megabayt vb. Şeklinde biçimlendirir.


12
kesinlikle ANDROID için en iyi cevap olmalı. Ek kütüphaneye gerek yok. +1
dieter

11
İçinden geçmek zorunda olmandan nefret ediyorum Context.
Jared Burrows

4
Kesinlikle ANDROID için en iyi cevap olmalı.
shridutt kothari

5
İçerik'i geçersiniz, böylece kullanıcının geçerli Yerel Ayarına çevrilir. Aksi takdirde çok kullanışlı bir işlev olmaz.
phreakhead

7
Bunu bilmeden kabul edilen cevabı kullanıyordum. Sadece belirtmek gerekirse, Build.VERSION_CODES.N ve önceki sürümlerde, bunun yerine 1024 = güçler kullanılır, KB = 1024 bayt, MB = 1.048.576 bayt, vb. O'dan itibaren, önekler SI sistemindeki standart anlamlarında kullanılır. yani kB = 1000 bayt, MB = 1.000.000 bayt vb.
HendraWD

57

Birimler arasındaki faktör (örn. B, KB, MB vb.) 1024 = 2 ^ 10 olduğu için basitlikten ödün vermeden yavaş Math.pow()ve Math.log()yöntemleri kullanmaktan tamamen kaçınabiliriz . LongSınıf, kodda numberOfLeadingZeros()biz büyüklük değeri düşer hangi birim anlatmak için kullanabileceğiniz yöntemi.

Anahtar nokta: Boyut birimleri 10 bitlik bir mesafeye sahiptir (1024 = 2 ^ 10), en yüksek 1 bitin konumu anlamına gelir - veya diğer bir deyişle, önde gelen sıfırların sayısı - 10'a kadar değişir (Bayt = KB * 1024, KB = MB * 1024 vb.).

Baştaki sıfır sayısı ile boyut birimi arasındaki ilişki:

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

Son kod:

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

Aynı soruyu son zamanlarda sordum:

Dosya boyutunu MB, GB vb. Olarak biçimlendirin

Hazır bir yanıt olmasa da, çözümle yaşayabilirim:

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

Test kodu:

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

Çıktı (Almanca Yerel ayarımda):

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

Düzenleme: Google Guava için bu işlevi talep eden bir Sorun açtım . Belki birisi onu desteklemeyi umursar.


2
0 neden geçersiz dosya boyutunda?
aioobe

@aioobe benim kullanım durumumda (yüklenen bir dosyanın boyutunu gösteriyor), ama tartışmasız bu evrensel değil
Sean Patrick Floyd

Son satırı NumberFormat.getFormat ("#, ## 0. #"). Biçimine (sonuç) + "" + birim döndürecek şekilde değiştirirseniz; GWT'de de çalışıyor! Bunun için teşekkürler, hala Guava'da değil.
tom

9

Bu aioobe cevabının değiştirilmiş bir versiyonudur .

değişiklikler:

  • Localeparametresi, çünkü bazı diller .diğerlerini ,ondalık nokta olarak kullanır .
  • okunabilir kod

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

Sadece ayırıcı sembolleri için bir Locale parametresi boyunca geçmek biraz karışık sonuçlardır, ancak daha sonra Fransız gibi Baytlar için farklı bir sembol kullanan dilleri de hesaba katmak için birimi yerelleştirmeyin.
Nzall

@Nzall Bunu mu demek istediniz? Wikipedia artık yaygın olmadığını belirtiyor. Başka, referansınız var mı?
Christian Strempfer

7

Android kullanıyorsanız android.text.format.Formatter.formatFileSize () yöntemini kullanabilirsiniz .

Alternativey, işte bu popüler gönderiye dayanan bir çözüm :

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

Veya Kotlin'de:

/**
 * 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()
}

For-loop'unuzda bire bir hata var gibi görünüyor. Bence öyle olmalı unitsCountve olmamalı unitsCount-1.
aioobe

@aioobe ama bu i == unitsCount, yani "charAt" başarısız olacağı anlamına gelir i == 6 döngü dönebilir anlamına gelir ...
android geliştirici

if(result<unit) break;ondan önce içeri girecek. Telaşa gerek yok. (Test ederseniz, for-loop koşulunu tamamen atlayabileceğinizi fark edeceksiniz.)
aioobe

@aioobe Doğru, "uzun" değişken tipini işlediğim varsayımından dolayı (ki bu doğru). Ayrıca, birimlerin en azından yazdıklarım olacağı varsayımına dayanmaktadır. Daha az birim kullanırsanız, garip sonuçlar üretir (1000'den büyük değerler yerine 1'den küçük değerleri tercih eder).
android geliştirici

@aioobe Doğru. Düzelteceğim. BTW, algoritmanız garip bir sonuç da sağlayabilir. argüman olarak "999999, true" ifadesini vermeyi deneyin. "1000.0 kB" gösterecektir, bu yüzden yuvarlanır, ancak insanlar bunu gördüğünde merak edebilirler: 1000MB = 1MB olarak neden 1MB gösteremiyorlar ... Bunun nasıl ele alınması gerektiğini düşünüyorsunuz? String.format yüzünden, ama nasıl düzeltilmesi gerektiğinden emin değilim.
android geliştirici

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

Bunu seviyorum çünkü takip etmesi ve anlaması kolay.
Joshua Pinter

6

Bayt Birimleri bunu şöyle yapmanızı sağlar:

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

Aradım başka kütüphane yazdım depolama üniteleri Eğer böyle yapmak sağlar:

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

Belirli bir birimi zorlamak istiyorsanız bunu yapın:

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

Artık birim biçimlendirmesi içeren bir kütüphane var. Ben onu ekledi Triava sadece diğer mevcut kütüphane Android için biri görünüyor olarak, kütüphanede.

3 farklı sistemde (SI, IEC, JEDEC) ve çeşitli çıkış seçeneklerinde sayıları keyfi hassasiyetle biçimlendirebilir. Triava birimi testlerinden bazı kod örnekleri :

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

Tam kilo, mega değerleri yazdırma (burada W = Watt ile):

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

Çıktıyı özelleştirmek için bir DecimalFormat iletebilirsiniz:

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

Kilo veya mega değerlerde keyfi işlemler için, bunları bileşenlere ayırabilirsiniz:

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

2

Bu yayını güncellemek için çok geç olduğunu biliyorum! ama bununla biraz eğlendim:

Bir arayüz oluşturun:

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

StorageUnits sınıfı oluşturun:

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

Bunu aramak:

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

Çıktı:

21.4kB
2GB

2

Şans eseri birisine biraz zaman kazandırır, ya da sadece biraz eğlenmek için, bir Go sürümü. Kolaylık olması açısından, yalnızca ikili çıktı durumunu ekledim.

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

Sadece daha fazla dosya birimi ekleyin (varsa eksik) ve bu birime kadar birim boyutu göreceksiniz (dosyanız çok uzunsa) System.out.println ("Dosya boyutu uygun biçimde:" + bayt + "" + fileSizeUnits [dizin]); sizeToReturn = String.valueOf (bayt) + "" + fileSizeUnits [dizin]; return sizeToReturn; }


1

Yukarıdaki Java doğru mutabakat yanıtı için C # .net eşdeğeri aşağıdadır. (aşağıda daha kısa kodları olan başka bir tane daha vardır)

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

Teknik olarak, SI birimlerine sadık kalırsak, bu rutin sayıların düzenli kullanımı için çalışır. Uzmanlardan başka birçok iyi cevap var. Izgara görüntülemelerinde sayıların veritabanını yaptığınızı varsayalım, bunlardan performansı optimize edilmiş rutinleri kontrol etmeye değer.

Not: C # projesi yaparken bu soru / cevap google aramada en üste geldi çünkü yayınlandı.


1

Sen kullanabilirsiniz StringUtils ‘s TraditionalBinarPrefix:

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

1

biraz eski ama, ... org.springframework.util.unit.DataSize en azından hesaplama için bu gereksinime uygun olabilir, o zaman basit bir dekoratör


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

Bu cevap, çalışırken, @ user601806 tarafından önceki bir cevap için bir tamamlayıcıdır: stackoverflow.com/a/4888400/3987745 Bu cevabın çalışması için Apache Commons IO'ya ( commons.apache.org/proper/ commons-io ) bağımlılık.
Edward Quixote

0

JSR 363'ü denediniz mi? Unicode CLDR ( GitHub: uom sistemlerinde ) gibi birim genişletme modülleri sizin için her şeyi yapar.

MetricPrefixHer uygulamada dahil kullanabilirsiniz veya BinaryPrefix(yukarıdaki örneklerin bazılarıyla karşılaştırılabilir) ve örneğin Hindistan'da veya yakındaki bir ülkede yaşıyor ve çalışıyorsanız, IndianPrefix(ayrıca uom-sistemlerinin ortak modülünde) "Crore" Bayt "veya" Lakh Bayt "da.


0

Belki bu kodu kullanabilirsiniz (C # ile):

        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

Tam bilgi almak için aşağıdaki işlevi kullanın, ATM_CashWithdrawlKavramın temelini alarak üretilir.

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

Aşağıdaki formatı almak için facebookarchive-StringUtils kodunu değiştirdim . Kullandığınızda Aynı biçimi alacak 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;
}

Yukarıdaki yöntemlerin örnek kullanımı:

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

Biçimin üstündeki bayt sayısı

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

Zamanı insan tarafından okunabilir biçimde görüntülemek için bu işlevi kullanın millisToShortDHMS(long duration).


0

İşte @aioobe'den kotlin'e dönüştürülmüş dönüşüm

/**
 * 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)
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.