Как преобразовать размер байта в читаемый человеком формат в java?
Как преобразовать размер байта в читаемый человеком формат в Java? Как 1024 должны стать "1 Кб" и 1024*1024 должен стать "1 Мб".
Мне надоело писать этот метод утилиты для каждого проекта. Есть ли статические методы в Apache Commons Для этого?
20 ответов
вот мой идти на него (без петель и обрабатывает как единицы СИ и двоичные единицы):
public static String humanReadableByteCount(long bytes, boolean si) {
int unit = si ? 1000 : 1024;
if (bytes < unit) return bytes + " B";
int exp = (int) (Math.log(bytes) / Math.log(unit));
String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp-1) + (si ? "" : "i");
return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
}
пример:
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)
статьи: Java: форматирование размера байта в удобочитаемый формат
FileUtils.byteCountToDisplaySize(long size)
будет работать, если ваш проект может зависеть от org.apache.commons.io
.
используйте Android builtin Class
для Android есть класс форматер. Только один подобный код, и вы закончите.
android.text.format.Formatter.formatShortFileSize(activityContext, bytes);
Это как formatFileSize()
, но пытается генерировать более короткие числа (показывая меньше десятичных знаков).
android.text.format.Formatter.formatFileSize(activityContext, bytes);
форматы размер содержимого, чтобы быть в форме байт, килобайт, мегабайт и т. д.
мы можем полностью избежать использования медленного Math.pow()
и Math.log()
методы без жертвовать простотой с фактора между блоками (например B, KB, MB etc.) является 1024, что составляет 2^10. The Long
класс имеет удобный numberOfLeadingZeros()
метод, который мы можем использовать, чтобы сказать, в какую единицу попадает значение размера.
ключевой момент: единицы размера имеют расстояние 10 бит (1024=2^10), что означает позицию самого высокого 1 бит - или другими словами ряд ведущих нули - отличаются на 10 (байт=КБ*1024 Кб=МБ*1024 и т. д.).
корреляция между количеством ведущих нулей и единицей размера:
# of leading 0's Size unit
-------------------------------
>53 B (Bytes)
>43 KB
>33 MB
>23 GB
>13 TB
>3 PB
<=2 EB
код:
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));
}
недавно я задал тот же вопрос:
размер файла формата как МБ, ГБ ЕТК
пока нет ответа из коробки, я могу жить с решением:
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;
}
тестовый код:
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));
}
}
вывод (на моем немецком языке):
1 B
4,2 KB
41,4 MB
3,3 GB
Edit: я открыл проблема с запросом этой функции для Google Guava. Возможно, кто-то захочет поддержать его.
Если вы используете Android, вы можете просто использовать праматерии.formatFileSize () .
Alternativey, вот решение, основанное на этот популярный пост :
/**
* 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;
}
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);
}
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 "???";
}
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";
}
}
теперь доступна одна библиотека, содержащая форматирование единиц. Я добавил его в triava библиотека, поскольку единственная другая существующая библиотека, похоже, предназначена для Android.
оно может форматировать номера с произвольной точностью, в 3 различных системах (SI, IEC, JEDEC) и различных вариантах выхода. Вот несколько примеров кода из модульные тесты triava:
UnitFormatter.formatAsUnit(1126, UnitSystem.SI, "B");
// = "1.13kB"
UnitFormatter.formatAsUnit(2094, UnitSystem.IEC, "B");
// = "2.04KiB"
печать точного кило, мега значений (здесь С W = Watt):
UnitFormatter.formatAsUnits(12_000_678, UnitSystem.SI, "W", ", ");
// = "12MW, 678W"
вы можете передать DecimalFormat для настройки вывода:
UnitFormatter.formatAsUnit(2085, UnitSystem.IEC, "B", new DecimalFormat("0.0000"));
// = "2.0361KiB"
для произвольных операций над значениями кило или мега вы можете разделить их на компоненты:
UnitComponent uc = new UnitComponent(123_345_567_789L, UnitSystem.SI);
int kilos = uc.kilo(); // 567
int gigas = uc.giga(); // 123
Байтовые Блоки позволяет сделать это так:
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));
Я написал еще одну библиотеку под названием хранилище-блоки, что позволяет сделать это так:
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);
Если вы хотите заставить определенный блок, сделайте следующее:
String formattedUnit9 = StorageUnits.formatAsKibibyte(input2);
String formattedUnit10 = StorageUnits.formatAsCommonMegabyte(input2);
Assert.assertEquals("1024.00 KiB", formattedUnit9);
Assert.assertEquals("1.00 MB", formattedUnit10);
Я знаю, что слишком поздно обновлять этот пост! но мне было весело с этим:
создать интерфейс:
public interface IUnits {
public String format(long size, String pattern);
public long getUnitSize();
}
создать класс 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.#");
}
}
называем это:
class Main {
public static void main(String... args) {
System.out.println(StorageUnits.format(21885));
System.out.println(StorageUnits.format(2188121545L));
}
}
выход:
21.4kB
2GB
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;
}
просто добавьте больше файловых единиц (если они отсутствуют), и вы увидите размер единицы до этой единицы (если ваш файл имеет такую длину) Система.из.println ("размер файла в правильном формате:" + байты + "" + fileSizeUnits[индекс]); sizeToReturn = строка.valueOf (байты) + "" + fileSizeUnits[индекс]; возврат sizeToReturn; }
вот эквивалент C# .net для правильного консенсусного ответа Java выше. (есть еще один ниже, которые имеют более короткие коды)
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);
}
Технически говоря, если мы придерживаемся единиц СИ, эта процедура работает для любого регулярного использования чисел. Есть много других хороших ответов от экспертов. Предположим, вы делаете привязку данных чисел в gridviews, стоит проверить оптимизированные для производительности процедуры из них.
PS: опубликовано, потому что этот вопрос/ответ пришел сверху в поиске google, пока я делаю проект c#.
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);
ты пробовал JSR 363? Свои модули расширения блока как Unicode CLDR (в GitHub: uom-systems) делать все это для вас.
можно использовать MetricPrefix
включено в каждую реализацию или BinaryPrefix
(сопоставимо с некоторыми примерами выше), и если вы, например, живете и работаете в Индии или соседней стране,IndianPrefix
(также В общем модуле uom-систем) позволяет использовать и форматировать "Crore Bytes" или "Lakh Bytes".
можно использовать StringUtils ' s TraditionalBinarPrefix
:
public static String humanReadableInt(long number) {
return TraditionalBinaryPrefix.long2String(number,””,1);
}
возможно, вы можете использовать этот код (в 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";
в случае, если это сэкономит кому-то немного времени, или, может быть, просто для удовольствия, вот версия Go. Для простоты я включил только случай двоичного вывода.
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)
}