Wie konvertiere ich die Bytegröße in Java in ein lesbares Format?

556

Wie konvertiere ich die Bytegröße in Java in ein lesbares Format? Wie 1024 sollte "1 Kb" und 1024 * 1024 sollte "1 Mb" werden.

Ich habe es satt, diese Dienstprogrammmethode für jedes Projekt zu schreiben. Gibt es dafür in Apache Commons statische Methoden ?

Igor Mukhin
quelle
32
Wenn Sie die standardisierten Einheiten verwenden, sollte 1024 zu "1 KB" und 1024 * 1024 zu "1 MB" werden. en.wikipedia.org/wiki/Binary_prefix
Pascal Cuoq
@Pascal: Es sollte mehrere Funktionen oder eine Option geben, um die Basis und die Einheit anzugeben.
Aaron Digulla
Mögliches Duplikat der
Formatdateigröße
3
@Pascal Cuoq: Danke für den Hinweis. Erst als ich es las, wurde mir klar, dass wir hier in der EU gesetzlich verpflichtet sind, die richtigen Präfixe zu verwenden.
JeremyP
2
@DerMike Du hast erwähnt, dass "Bis eine solche Bibliothek existiert". Dies ist jetzt wahr geworden. :-) stackoverflow.com/questions/3758606/…
Christian Esken

Antworten:

1310

Unterhaltsame Tatsache: Das hier veröffentlichte Original-Snippet war das am meisten kopierte Java-Snippet aller Zeiten bei Stack Overflow und war fehlerhaft. Es wurde behoben, aber es wurde chaotisch.

Ganze Geschichte in diesem Artikel: Das am meisten kopierte StackOverflow-Snippet aller Zeiten ist fehlerhaft!

Quelle: Formatieren der Bytegröße in ein lesbares Format 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());
}

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

Beispielausgabe:

                              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
quelle
12
Ich bevorzuge 1,0 KB. Dann ist klar, wie viele signifikante Zahlen die Ausgabe beinhaltet. (Dies scheint auch das Verhalten von beispielsweise dem duBefehl unter Linux zu sein.)
aioobe
19
Ich denke, jeder sollte beachten, dass in Ihrem Projekt der Kunde Werte in Basis 2 (geteilt durch 1024) sehen möchte, jedoch mit einem gemeinsamen Präfix. Nicht KiB, MiB, GiB usw. Verwenden Sie dafür KB, MB, GB, TB.
Borys
27
@Borys Die Verwendung von "KB" für "1024 Byte" ist falsch. Tu das nicht.
Endolith
8
Die Leser werden es lernen. Besser etwas, mit dem sie nicht vertraut sind und das sie lernen können, als etwas falsch zu machen. Wenn Sie KB schreiben, erwartet ein Benutzer, der damit vertraut ist, 1000 und ein Benutzer, der nicht vertraut ist, 1024.
Kap
16
Antwort komplett neu geschrieben. Viele der obigen Kommentare sind veraltet.
Aioobe
305

FileUtils.byteCountToDisplaySize(long size)würde funktionieren, wenn Ihr Projekt abhängen kann org.apache.commons.io.

JavaDoc für diese Methode

user601806
quelle
18
Ich habe bereits Commons-Io in meinem Projekt, habe aber aufgrund des Rundungsverhaltens (siehe Link für JavaDoc) den Code von Aioobe verwendet
Iravanchi
3
Gibt es ein Dienstprogramm für den umgekehrten Vorgang? Erhalten der Byteanzahl von der vom Menschen lesbaren Byteanzahl?
Arunmoezhi
6
Leider ist diese Funktion nicht länderspezifisch. Auf Französisch beispielsweise werden Bytes immer als "Oktette" bezeichnet. Wenn Sie einem französischen Benutzer eine 100-KB-Datei anzeigen möchten, lautet die korrekte Bezeichnung 100 Ko.
Tacroy
@ Tacroy Mit dem UnitFormatter in der Triava-Bibliothek können Sie Oktette ausgeben. Sie können jede Einheit für Bytes, Watt oder Oktette übergeben. Beispiel, leicht modifiziert gegenüber den Beispielen in github.com/trivago/triava : UnitFormatter.formatAsUnit (1126, UnitSystem.SI, "o"); // = "1.13 ko" Weitere Beispiele in: stackoverflow.com/questions/3758606/…
Christian Esken
5
Dies rundet auf das nächste GB ab, wenn> 1 GB, was bedeutet, dass die Genauigkeit, die Sie daraus erhalten, variiert
tksfz
180

Verwenden Sie die in Android integrierte Klasse

Für Android gibt es eine Klasse Formatter . Nur eine Codezeile und Sie sind fertig.

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

Es ist wie formatFileSize(), aber es wird versucht, kürzere Zahlen zu generieren (mit weniger Dezimalstellen).

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

Formatiert eine Inhaltsgröße in Form von Bytes, Kilobytes, Megabytes usw.

AZ_
quelle
12
sollte definitiv die beste Antwort für ANDROID sein. Keine zusätzlichen Bibliotheken erforderlich. +1
Dieter
11
Ich hasse die Tatsache, dass du vorbeikommen musst Context.
Jared Burrows
4
Sollte definitiv die beste Antwort für ANDROID sein.
Shridutt Kothari
5
Sie übergeben den Kontext, damit er in das aktuelle Gebietsschema des Benutzers übersetzt wird. Sonst wäre es keine sehr nützliche Funktion.
Phreakhead
7
Ich habe die akzeptierte Antwort verwendet, bevor ich das weiß. Zu beachten ist, dass in Build.VERSION_CODES.N und früheren Versionen stattdessen Potenzen von 1024 mit KB = 1024 Byte, MB = 1.048.576 Byte usw. verwendet werden. Ab O werden die Präfixe in ihrer Standardbedeutung im SI-System verwendet , also kB = 1000 Bytes, MB = 1.000.000 Bytes usw.
HendraWD
57

Wir können die Verwendung der langsamen Math.pow()und Math.log()Methoden vollständig vermeiden, ohne die Einfachheit zu beeinträchtigen, da der Faktor zwischen den Einheiten (z. B. B, KB, MB usw.) 1024 beträgt, was 2 ^ 10 ist. Die LongKlasse verfügt über eine praktische numberOfLeadingZeros()Methode, mit der wir feststellen können, in welche Einheit der Größenwert fällt.

Schlüsselpunkt: Größeneinheiten haben einen Abstand von 10 Bit (1024 = 2 ^ 10), was bedeutet, dass sich die Position des höchsten 1 Bits - oder mit anderen Worten die Anzahl der führenden Nullen - um 10 unterscheidet (Bytes = KB * 1024, KB = MB) * 1024 usw.).

Korrelation zwischen Anzahl der führenden Nullen und Größeneinheit:

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

Der endgültige Code:

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
quelle
24

Ich habe kürzlich dieselbe Frage gestellt:

Formatieren Sie die Dateigröße als MB, GB usw.

Es gibt zwar keine sofort einsatzbereite Antwort, aber ich kann mit der Lösung leben:

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

Testcode:

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

Ausgabe (in meinem deutschen Gebietsschema):

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

Bearbeiten: Ich habe ein Problem geöffnet , in dem diese Funktionalität für Google Guava angefordert wurde . Vielleicht würde es jemand gerne unterstützen.

Sean Patrick Floyd
quelle
2
Warum ist 0 eine ungültige Dateigröße?
Aioobe
@aioobe war es in meinem Anwendungsfall (Anzeige der Größe einer hochgeladenen Datei), aber das ist wohl nicht universell
Sean Patrick Floyd
Wenn Sie die letzte Zeile ändern, um NumberFormat.getFormat ("#, ## 0. #") Zurückzugeben. Format (Ergebnis) + "" + unit; es funktioniert auch in GWT! Danke dafür, es ist immer noch nicht in Guave.
Tom
9

Dies ist eine modifizierte Version der Antwort von aioobe .

Änderungen:

  • LocaleParameter, da einige Sprachen .und andere ,als Dezimalpunkt verwenden.
  • Für Menschen lesbarer Code

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
quelle
Es ist ein bisschen uneinheitlich, einen Locale-Parameter nur für die Trennsymbole weiterzugeben, aber dann nicht auch die Einheit zu lokalisieren, um Sprachen zu berücksichtigen, die auch ein anderes Symbol für Bytes verwenden, wie z. B. Französisch.
Nzall
@ Nzall Meinst du das Oktett? Wikipedia gibt an, dass es nicht mehr üblich ist. Sonst haben Sie eine Referenz?
Christian Strempfer
7

Wenn Sie Android verwenden, können Sie einfach android.text.format.Formatter.formatFileSize () verwenden .

Alternativ, hier ist eine Lösung, die auf diesem beliebten Beitrag basiert :

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

Oder in 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()
}
Android-Entwickler
quelle
Sie scheinen einen Fehler nach dem anderen in Ihrer for-Schleife zu haben. Ich denke es sollte sein unitsCountund nicht unitsCount-1.
Aioobe
@aioobe, aber dies bedeutet, dass die Schleife anhalten kann, wenn i == unitCount, was bedeutet, dass i == 6, was bedeutet, dass "charAt" fehlschlägt ...
Android-Entwickler
if(result<unit) break;wird vorher eintreten. Keine Sorge. (Wenn Sie es testen, werden Sie feststellen, dass Sie die for-Schleife-Bedingung vollständig überspringen können.)
aioobe
@aioobe Richtig, das liegt an der Annahme (was richtig ist), dass ich den "langen" Variablentyp verarbeite. Es basiert auch auf der Annahme, dass die Einheiten mindestens das sind, was ich geschrieben habe. Wenn Sie weniger Einheiten verwenden, führt dies zu seltsamen Ergebnissen (bevorzugt Werte unter 1 anstelle von Werten über 1000).
Android-Entwickler
@aioobe Richtig. Ich werde es reparieren. Übrigens kann Ihr Algorithmus auch ein seltsames Ergebnis liefern. Geben Sie als Argumente "999999, true" ein. Es wird "1000.0 kB" angezeigt, also ist es gerundet, aber wenn die Leute es sehen, können sie sich fragen: Warum kann es nicht 1 MB anzeigen, da 1000 KB = 1 MB ... Wie sollte dies Ihrer Meinung nach gehandhabt werden? Es liegt am String.format, aber ich bin mir nicht sicher, wie es behoben werden soll.
Android-Entwickler
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
quelle
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
quelle
Ich mag das, weil es leicht zu folgen und leicht zu verstehen ist.
Joshua Pinter
6

Mit Byte Units können Sie dies folgendermaßen tun:

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

Ich habe eine andere Bibliothek namens Speichereinheiten geschrieben , mit der Sie dies folgendermaßen tun können:

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

Wenn Sie eine bestimmte Einheit erzwingen möchten, gehen Sie folgendermaßen vor:

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

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

Es ist jetzt eine Bibliothek verfügbar, die die Formatierung von Einheiten enthält. Ich habe es der Triava- Bibliothek hinzugefügt , da die einzige andere vorhandene Bibliothek eine für Android zu sein scheint.

Es kann Zahlen mit beliebiger Genauigkeit in 3 verschiedenen Systemen (SI, IEC, JEDEC) und verschiedenen Ausgabeoptionen formatieren. Hier sind einige Codebeispiele aus den Triava-Unit-Tests :

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

Drucken von exakten Kilo- und Megawerten (hier mit W = Watt):

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

Sie können ein DecimalFormat übergeben, um die Ausgabe anzupassen:

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

Für beliebige Operationen mit Kilo- oder Megawerten können Sie diese in Komponenten aufteilen:

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

Ich weiß, dass es zu spät ist, diesen Beitrag zu aktualisieren! aber ich hatte ein bisschen Spaß damit:

Erstellen Sie eine Schnittstelle:

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

Erstellen Sie die StorageUnits-Klasse:

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

Nennen:

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

Ausgabe:

21.4kB
2GB
Ahmad AlMughrabi
quelle
2

In der Off-Chance spart es jemandem ein bisschen Zeit oder vielleicht nur für ein bisschen Spaß, hier ist eine Go-Version. Der Einfachheit halber habe ich nur den Fall der binären Ausgabe aufgenommen.

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

Fügen Sie einfach weitere Dateieinheiten hinzu (falls vorhanden), und Sie sehen die Einheitengröße bis zu dieser Einheit (wenn Ihre Datei so lang ist). System.out.println ("Dateigröße im richtigen Format:" + Bytes + "" + fileSizeUnits [Index]); sizeToReturn = String.valueOf (Bytes) + "" + fileSizeUnits [index]; return sizeToReturn; }}

Vishwajit R. Shinde
quelle
1

Hier ist das C # .net-Äquivalent für die oben angegebene korrekte Java-Konsensantwort. (Es gibt eine andere unten, die kürzere Codes haben)

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

Technisch gesehen funktioniert diese Routine, wenn wir uns an SI-Einheiten halten, für jede regelmäßige Verwendung von Zahlen. Es gibt viele andere gute Antworten von Experten. Angenommen, Sie führen die Datenbindung von Zahlen in Gridviews durch. Es lohnt sich, leistungsoptimierte Routinen daraus zu überprüfen.

PS: Gepostet, weil diese Frage / Antwort bei der Google-Suche während des C # -Projekts ganz oben stand.

Chan Fun Chiat
quelle
1

Sie können mit StringUtils ‚s TraditionalBinarPrefix:

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

etwas alt, aber ... org.springframework.util.unit.DataSize könnte zumindest für die Berechnung zu dieser Anforderung passen, dann reicht ein einfacher Dekorateur

Tama
quelle
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
quelle
Diese Antwort ist zwar eine Ergänzung zu einer früheren Antwort in diesem Thread von @ user601806: stackoverflow.com/a/4888400/3987745 Damit diese Antwort funktioniert, benötigen Sie Apache Commons IO ( commons.apache.org/proper/). commons-io ) Abhängigkeit.
Edward Quijote
0

Haben Sie JSR 363 ausprobiert ? Die Einheitenerweiterungsmodule wie Unicode CLDR (in GitHub: uom-systems ) erledigen das alles für Sie.

Sie können MetricPrefixin jeder Implementierung enthalten oder BinaryPrefix(vergleichbar mit einigen der obigen Beispiele) und wenn Sie zB in Indien oder einem nahe gelegenen Land leben und arbeiten, IndianPrefix(auch im gemeinsamen Modul von UOM-Systemen) können Sie "Crore" verwenden und formatieren Bytes "oder" Lakh Bytes "auch.

Werner Keil
quelle
0

Vielleicht können Sie diesen Code verwenden (in 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
quelle
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
quelle
0

Verwenden Sie die folgende Funktion, um genaue Informationen zu erhalten. Diese werden anhand der ATM_CashWithdrawlKonzeptbasis generiert .

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

Ich habe gerade den Code von facebookarchiveStringUtils geändert , um das folgende Format zu erhalten. Das gleiche Format erhalten Sie, wenn Sie apache.hadoop- verwenden.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;
}

Beispiel für die Verwendung der oben genannten Methoden:

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, um über das Format zu gelangen

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

Verwenden Sie diese Funktion, um die Zeit in einem für Menschen lesbaren Format anzuzeigen millisToShortDHMS(long duration).

Yash
quelle
0

Hier ist die Konvertierung von @aioobe in Kotlin konvertiert

/**
 * 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
quelle