Como converter tamanho de byte em formato legível por humanos em Java?

556

Como converter tamanho de byte em formato legível por humanos em Java? Assim, 1024 deve se tornar "1 Kb" e 1024 * 1024 deve se tornar "1 Mb".

Estou meio cansado de escrever esse método utilitário para cada projeto. Existem métodos estáticos no Apache Commons para isso?

Igor Mukhin
fonte
32
Se você usar as unidades padronizadas, 1024 deve se tornar "1KiB" e 1024 * 1024 deve se tornar "1MiB". pt.wikipedia.org/wiki/Binary_prefix
Pascal Cuoq
@ Pascal: Deve haver várias funções ou uma opção para especificar a base e a unidade.
Aaron Digulla 21/09/10
possível duplicado do tamanho do arquivo Format como MB, GB etc
Aaron Digulla
3
Pascal Cuoq: Obrigado pela referência. Até o momento, eu não percebi que aqui na UE somos obrigados a usar os prefixos corretos por lei.
precisa saber é o seguinte
2
@DerMike Você mencionou que "Até que essa biblioteca exista". Isso agora se tornou verdade. :-) stackoverflow.com/questions/3758606/…
Christian Esken

Respostas:

1310

Curiosidade: o snippet original postado aqui foi o snippet Java mais copiado de todos os tempos no Stack Overflow e com defeito. Foi consertado, mas ficou confuso.

Artigo completo neste artigo: O snippet StackOverflow mais copiado de todos os tempos é falho!

Fonte: Formatação do tamanho do byte para o formato legível por humanos | 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ário (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());
}

Exemplo de saída:

                              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
fonte
12
Eu prefiro 1,0 KB. Então fica claro quantos números significativos a produção implica. (Isso também parece ser o comportamento de, por exemplo, o ducomando no Linux.)
aioobe
19
Eu acho que todos devem observar que, no seu projeto, o cliente deseja ver valores na base 2 (dividido por 1024), mas com prefixo comum. Não KiB, MiB, GiB etc. Use KB, MB, GB, TB para isso.
Borys #
27
@Borys Usar "KB" para significar "1024 bytes" está errado. Não faça isso.
endolith
8
Os leitores vão aprender. Melhor algo que eles não estão familiarizados e podem aprender do que ter algo errado. Escrevendo KB um usuário que esteja familiarizado com ele vai esperar 1000 e um usuário que não está familiarizado esperam 1024.
kap
16
Resposta reescrita inteiramente. Muitos dos comentários acima são obsoletos.
Aioobe # 3/19
305

FileUtils.byteCountToDisplaySize(long size)funcionaria se o seu projeto pudesse depender org.apache.commons.io.

JavaDoc para este método

user601806
fonte
18
Já tenho commons-io no meu projeto, mas acabou usando o código de aioobe, por causa do comportamento de arredondamento (veja o link para JavaDoc)
Iravanchi
3
existe um utilitário para fazer a operação reversa. Obtendo a contagem de bytes da contagem de bytes legível por humanos?
Arunmoezhi
6
Infelizmente, esta função não reconhece o código de idioma; em francês, por exemplo, eles sempre chamam bytes de "octetos"; portanto, se você deseja exibir um arquivo de 100 KB para um usuário francês, o rótulo correto seria 100 Ko.
Tacroy
@Tacroy Você pode obter uma saída de octetos com o UnitFormatter na biblioteca do triava. Você pode passar qualquer unidade para bytes, watts ou octetos. Exemplo, ligeiramente modificado a partir dos exemplos em github.com/trivago/triava : UnitFormatter.formatAsUnit (1126, UnitSystem.SI, "o"); // = "1,13 ko" Mais exemplos em: stackoverflow.com/questions/3758606/…
Christian Esken 5/17/17
5
este rodadas para o gb mais próximo quando> 1 gb, o que significa que a precisão que você sair dela varia
tksfz
180

Usar classe interna do Android

Para o Android, existe uma classe Formatador . Apenas uma linha de código e pronto.

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

É como formatFileSize(), mas tentando gerar números mais curtos (mostrando menos casas decimais).

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

Formata um tamanho de conteúdo para estar na forma de bytes, kilobytes, megabytes etc.

AZ_
fonte
12
deve ser a melhor resposta para o ANDROID definitivamente. Nenhuma biblioteca extra necessária. +1
dieter
11
Eu odeio o fato de você ter que passar Context.
Jared Burrows
4
Deve ser a melhor resposta para o ANDROID definitivamente.
shridutt kothari
5
Você passa no Contexto para que seja traduzido para a localidade atual do usuário. Caso contrário, não seria uma função muito útil.
Phreakhead #:
7
Eu estava usando a resposta aceita antes de saber isso. Apenas para ser observado, em Build.VERSION_CODES.N e versões anteriores, são usados ​​poderes de 1024, com KB = 1024 bytes, MB = 1.048.576 bytes, etc. A partir de O, os prefixos são usados ​​em seus significados padrão no sistema SI , de modo kB = 1000 bytes, MB = 1.000.000 bytes, etc.
HendraWD
57

Podemos evitar completamente o uso dos métodos lento Math.pow()e Math.log()sem sacrificar a simplicidade, pois o fator entre as unidades (por exemplo, B, KB, MB etc.) é 1024, que é 2 ^ 10. A Longclasse possui um numberOfLeadingZeros()método útil que podemos usar para informar em qual unidade o valor do tamanho se enquadra.

Ponto-chave: as unidades de tamanho têm uma distância de 10 bits (1024 = 2 ^ 10), o que significa que a posição do 1 bit mais alto - ou seja, o número de zeros à esquerda - difere em 10 (Bytes = KB * 1024, KB = MB * 1024 etc.).

Correlação entre o número de zeros à esquerda e a unidade de tamanho:

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

O código final:

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

Fiz a mesma pergunta recentemente:

Formate o tamanho do arquivo como MB, GB, etc.

Embora não haja uma resposta pronta para uso, eu posso viver com a solução:

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

Código do teste:

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

Saída (na minha localidade alemã):

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

Editar: eu abri um problema solicitando essa funcionalidade para o Google Guava . Talvez alguém se importasse em apoiá-lo.

Sean Patrick Floyd
fonte
2
Por que 0 é um tamanho de arquivo inválido?
aioobe
@aioobe foi em meu caso de uso (que mostra o tamanho de um arquivo carregado), mas sem dúvida isso não é universal
Sean Patrick Floyd
Se você alterar a última linha para retornar NumberFormat.getFormat ("#, ## 0. #"). Format (result) + "" + unit; Também funciona no GWT! Obrigado por isso, ainda não está na Goiaba.
tom
9

Esta é uma versão modificada da resposta do aioobe .

Alterar:

  • Localeparâmetro, porque alguns idiomas usam .e outros ,como ponto decimal.
  • código legível por humanos

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
fonte
É um pouco misto de resultados passar um parâmetro Locale apenas para os símbolos separadores, mas também não localize a unidade para dar conta de idiomas que também usam um símbolo diferente para bytes, como o francês.
Nzall 29/10/19
@Nzall Você quer dizer o octeto? A Wikipedia está afirmando que não é mais comum. Senão, você tem uma referência?
Christian Strempfer 29/10/19
7

Se você usa o Android, pode simplesmente usar android.text.format.Formatter.formatFileSize () .

Como alternativa, aqui está uma solução baseada neste post popular :

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

Ou em 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()
}
desenvolvedor android
fonte
Você parece ter um erro de um por um no loop for. Eu acho que deveria ser unitsCounte não unitsCount-1.
aioobe
@aioobe mas isso significa que o loop pode parar quando i == unitsCount, o que significa i == 6, o que significa que "charAt" falhará ...
desenvolvedor Android
if(result<unit) break;vai chutar antes disso. Não se preocupe. (Se você testá-lo, você vai perceber que você pode ignorar a condição de loop for inteiramente.)
aioobe
@aioobe Correto, isso é por causa da suposição (correta) de que eu manuseio o tipo de variável "long". Além disso, é baseado no pressuposto de que as unidades serão pelo menos o que escrevi. Se você usar menos unidades, produzirá resultados estranhos (preferirá valores menores que 1, em vez de valores maiores que 1000).
desenvolvedor Android
@aioobe Correct. Eu vou consertar isso. BTW, seu algoritmo também pode fornecer um resultado estranho. tente dar "999999, true" como argumentos. ele mostrará "1000,0 kB", então é arredondado, mas quando as pessoas o veem, podem se perguntar: por que não mostra 1 MB, como 1000 KB = 1 MB ... Como você acha que isso deve ser tratado? É por causa do String.format, mas não sei como deve ser corrigido.
desenvolvedor 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
fonte
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
fonte
Eu gosto disso porque é fácil de seguir e fácil de entender.
Joshua Pinter
6

As unidades de bytes permitem que você faça assim:

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

Eu escrevi outra biblioteca chamada storage-units que permite que você faça assim:

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

Caso você queira forçar uma determinada unidade, faça o seguinte:

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

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

Agora existe uma biblioteca disponível que contém a formatação da unidade. Adicionei- o à biblioteca triava , pois a única outra biblioteca existente parece ser uma para o Android.

Ele pode formatar números com precisão arbitrária, em 3 sistemas diferentes (SI, IEC, JEDEC) e várias opções de saída. Aqui estão alguns exemplos de código dos testes de unidade triava :

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

Imprimindo quilo exato, mega valores (aqui com W = Watt):

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

Você pode passar um DecimalFormat para personalizar a saída:

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

Para operações arbitrárias em quilo ou mega valores, é possível dividi-los em componentes:

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

Eu sei que é tarde demais para atualizar este post! mas me diverti um pouco com isso:

Crie uma interface:

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

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

Chame-o:

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

Resultado:

21.4kB
2GB
Ahmad AlMughrabi
fonte
2

Na hipótese de poupar alguém um pouco de tempo, ou talvez apenas por diversão, aqui está uma versão Go. Para simplificar, incluí apenas o caso de saída binária.

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

Basta adicionar mais unidades de arquivo (se houver alguma faltando) e você verá o tamanho da unidade nessa unidade (se o seu arquivo tiver esse tamanho) System.out.println ("Tamanho do arquivo no formato apropriado:" + bytes + "" + fileSizeUnits [índice]); sizeToReturn = String.valueOf (bytes) + "" + fileSizeUnits [index]; return sizeToReturn; }

Vishwajit R. Shinde
fonte
1

Aqui está o equivalente em C # .net para a resposta correta de consenso do Java acima. (há outro abaixo com códigos mais curtos)

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

Tecnicamente falando, se mantivermos as unidades SI, essa rotina funcionará para qualquer uso regular de números. Existem muitas outras boas respostas de especialistas. Suponha que você esteja fazendo a ligação de dados de números em visualizações de grade, vale a pena conferir as rotinas com desempenho otimizado.

PS: Publicado porque esta pergunta / resposta apareceu no topo da pesquisa do Google enquanto estou fazendo o projeto C #.

Chan Fun Chiat
fonte
1

Você pode usar StringUtils s’ TraditionalBinarPrefix:

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

um pouco antigo, mas ... org.springframework.util.unit.DataSize pode se adequar a esse requisito pelo menos para o cálculo, então um decorador simples fará

Tama
fonte
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
fonte
Esta resposta, enquanto funciona, é um complemento a uma resposta anterior neste tópico por @ user601806: stackoverflow.com/a/4888400/3987745 Para que esta resposta funcione, você precisa do Apache Commons IO ( commons.apache.org/proper/ commons-io ) dependência.
Edward Quixote
0

Você já experimentou o JSR 363 ? Seus módulos de extensão de unidade como Unicode CLDR (no GitHub: uom-systems ) fazem tudo isso para você.

Você pode usar MetricPrefixincluído em todas as implementações ou BinaryPrefix(comparável a alguns dos exemplos acima) e se, por exemplo, mora e trabalha na Índia ou em um país próximo IndianPrefix(também no módulo comum de uom-systems) permite usar e formatar "Crore Bytes "ou" Lakh Bytes "também.

Werner Keil
fonte
0

Talvez você possa usar este código (em 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
fonte
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
fonte
0

Use a função a seguir para obter informações exatas, geradas usando a base de ATM_CashWithdrawl conceito.

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

Acabei de modificar o código do facebookarchive-StringUtils para obter o formato abaixo. O mesmo formato que você obterá quando usar o 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;
}

Exemplo de uso dos métodos acima:

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 para obter o formato acima

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

Para exibir o tempo no formato legível por humanos, use esta função millisToShortDHMS(long duration).

Yash
fonte
0

aqui está a conversão de @aioobe convertida para 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
fonte