Java에서 바이트 크기를 사람이 읽을 수있는 형식으로 변환하는 방법은 무엇입니까? 1024처럼 “1Kb”가되어야하고 1024 * 1024는 “1Mb”가되어야합니다.
각 프로젝트에 대해이 유틸리티 방법을 작성하는 데 어려움이 있습니다. 이것을 위해 Apache Commons 에 정적 메소드가 있습니까?
답변
재미있는 사실 : 여기에 게시 된 원래 스 니펫은 스택 오버플로에서 가장 많이 복사 된 Java 스 니펫이며 결함이 있습니다. 수정되었지만 지저분 해졌습니다.
이 기사의 전체 기사 : 모든 시간 동안 가장 많이 복사 된 StackOverflow 스 니펫에 결함이 있습니다!
출처 : 바이트 크기를 사람이 읽을 수있는 형식으로 포맷 | 프로그래밍 가이드
SI (1k = 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());
}
이진수 (1K = 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());
}
출력 예 :
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)
답변
FileUtils.byteCountToDisplaySize(long size)
프로젝트가 의지 할 수 있다면 효과가있을 것입니다 org.apache.commons.io
.
답변
안드로이드 내장 클래스 사용
안드로이드에는 Formatter 클래스가 있습니다. 한 줄의 코드 만 있으면 완료됩니다.
android.text.format.Formatter.formatShortFileSize(activityContext, bytes);
그것은 formatFileSize()
같지만 더 짧은 숫자를 생성하려고합니다 (소수를 적게 표시 함).
android.text.format.Formatter.formatFileSize(activityContext, bytes);
콘텐츠 크기를 바이트, 킬로바이트, 메가 바이트 등의 형식으로 지정합니다.
답변
단위 사이의 요소 (예 : B, KB, MB 등)가 2 ^ 10 인 1024이므로 속도 Math.pow()
를 Math.log()
낮추지 않고 속도 와 방법을 사용하지 않아도됩니다. 이 Long
클래스에는 numberOfLeadingZeros()
크기 값에 속하는 단위를 알려주 는 편리한 메소드가 있습니다.
요점 : 크기 단위의 거리는 10 비트 (1024 = 2 ^ 10)이며 최상위 1 비트의 위치를 의미합니다. 즉, 선행 0 의 수는 10만큼 다릅니다 (바이트 = KB * 1024, KB = MB * 1024 등).
선행 0의 수와 크기 단위의 상관 관계 :
# 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
편집 : Google Guava 에이 기능을 요청 하는 문제를 열었습니다 . 아마도 누군가가 그것을 지원하려고 할 것입니다.
답변
이것은 aioobe ‘s answer의 수정 된 버전입니다 .
변경 사항 :
Locale
일부 언어는.
다른 언어,
를 소수점으로 사용하기 때문 입니다.- 사람이 읽을 수있는 코드
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);
}
답변
Android를 사용하는 경우 android.text.format.Formatter.formatFileSize () 를 사용하면됩니다 . .
대안으로, 이 인기있는 게시물을 기반으로 한 솔루션 이 있습니다 .
/**
* 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;
}
또는 코 틀린에서 :
/**
* 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()
}