[javascript] 바이트 단위의 파일 크기를 사람이 읽을 수있는 문자열로 변환

이 함수를 사용하여 파일 크기 (바이트)를 사람이 읽을 수있는 파일 크기로 변환합니다.

function getReadableFileSizeString(fileSizeInBytes) {
    var i = -1;
    var byteUnits = [' kB', ' MB', ' GB', ' TB', 'PB', 'EB', 'ZB', 'YB'];
    do {
        fileSizeInBytes = fileSizeInBytes / 1024;
        i++;
    } while (fileSizeInBytes > 1024);

    return Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i];
};

그러나 이것이 100 % 정확하지 않은 것 같습니다. 예를 들면 다음과 같습니다.

getReadableFileSizeString(1551859712); // output is "1.4 GB"

이러면 안 "1.5 GB"됩니까? 1024로 나누면 정밀도가 떨어지는 것처럼 보입니다. 내가 완전히 오해하고 있거나 더 좋은 방법이 있습니까?



답변

이진법 또는 십진법을 사용할지 여부에 따라 다릅니다.

예를 들어, RAM은 항상 이진수로 측정되므로 ~ 1.4GiB가 올바른 1551859712를 표현합니다.

반면에 하드 디스크 제조업체는 십진수를 사용하기를 원하므로 ~ 1.6GB라고 부릅니다.

그리고 혼란스럽게도 플로피 디스크는 두 시스템을 혼합하여 사용합니다. 1MB는 ​​실제로 1024000 바이트입니다.


답변

내가 쓴 것은 다음과 같습니다.

function humanFileSize(bytes, si=false, dp=1) {
  const thresh = si ? 1000 : 1024;

  if (Math.abs(bytes) < thresh) {
    return bytes + ' B';
  }

  const units = si
    ? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
    : ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
  let u = -1;
  const r = 10**dp;

  do {
    bytes /= thresh;
    ++u;
  } while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1);


  return bytes.toFixed(dp) + ' ' + units[u];
}


console.log(humanFileSize(5000, true))  // 5.0 kB
console.log(humanFileSize(5000, false))  // 4.9 KiB
console.log(humanFileSize(-10000000000000000000000000000))  // -8271.8 YiB
console.log(humanFileSize(999949, true))  // 999.9 kB
console.log(humanFileSize(999950, true))  // 1.0 MB
console.log(humanFileSize(999950, true, 2))  // 999.95 kB
console.log(humanFileSize(999500, true, 0))  // 1 MB


답변

계산의 다른 실시 예

function humanFileSize(size) {
    var i = Math.floor( Math.log(size) / Math.log(1024) );
    return ( size / Math.pow(1024, i) ).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i];
};


답변

다음은 새로운 국제 표준에 따라 숫자를 읽을 수있는 문자열로 변환하는 프로토 타입입니다.

큰 숫자를 나타내는 두 가지 방법이 있습니다. 1000 = 10 3 (기본 10) 또는 1024 = 2 10 (기본 2)의 배수로 표시 할 수 있습니다. 1000으로 나누면 SI 접두사 이름을 사용하고 1024로 나누면 IEC 접두사 이름을 사용하게됩니다. 문제는 1024로 나누는 것으로 시작합니다. 많은 응용 프로그램에서 SI 접두사 이름을 사용하고 일부 응용 프로그램은 IEC 접두사 이름을 사용합니다. 현재 상황은 혼란입니다. SI 접두사 이름이 표시되면 숫자를 1000 또는 1024로 나눈 것인지 알 수 없습니다

https://wiki.ubuntu.com/UnitsPolicy

http://en.wikipedia.org/wiki/Template:Quantities_of_bytes

Object.defineProperty(Number.prototype,'fileSize',{value:function(a,b,c,d){
 return (a=a?[1e3,'k','B']:[1024,'K','iB'],b=Math,c=b.log,
 d=c(this)/c(a[0])|0,this/b.pow(a[0],d)).toFixed(2)
 +' '+(d?(a[1]+'MGTPEZY')[--d]+a[2]:'Bytes');
},writable:false,enumerable:false});

이 함수에는 no가 포함되어 loop있으므로 다른 함수보다 빠릅니다.

용법:

IEC 접두사

console.log((186457865).fileSize()); // default IEC (power 1024)
//177.82 MiB
//KiB,MiB,GiB,TiB,PiB,EiB,ZiB,YiB

SI 접두사

console.log((186457865).fileSize(1)); //1,true for SI (power 1000)
//186.46 MB 
//kB,MB,GB,TB,PB,EB,ZB,YB

파일 크기를 계산하기 위해 항상 이진 모드를 사용했기 때문에 IEC를 기본값으로 설정했습니다 .1024의 거듭 제곱을 사용합니다.


짧은 oneliner 기능으로 그중 하나를 원한다면 :

function fileSizeSI(a,b,c,d,e){
 return (b=Math,c=b.log,d=1e3,e=c(a)/c(d)|0,a/b.pow(d,e)).toFixed(2)
 +' '+(e?'kMGTPEZY'[--e]+'B':'Bytes')
}
//kB,MB,GB,TB,PB,EB,ZB,YB

IEC

function fileSizeIEC(a,b,c,d,e){
 return (b=Math,c=b.log,d=1024,e=c(a)/c(d)|0,a/b.pow(d,e)).toFixed(2)
 +' '+(e?'KMGTPEZY'[--e]+'iB':'Bytes')
}
//KiB,MiB,GiB,TiB,PiB,EiB,ZiB,YiB

용법:

console.log(fileSizeIEC(7412834521));

기능에 대해 궁금한 점이 있으면


답변

sizeOf = function (bytes) {
  if (bytes == 0) { return "0.00 B"; }
  var e = Math.floor(Math.log(bytes) / Math.log(1024));
  return (bytes/Math.pow(1024, e)).toFixed(2)+' '+' KMGTP'.charAt(e)+'B';
}

sizeOf (2054110009);
// => “1.91GB”

sizeOf (7054110);
// => “6.73MB”

sizeOf ((3 * 1024 * 1024));
// => “3.00 MB”


답변

ReactJS 컴포넌트로서의 솔루션

Bytes = React.createClass({
    formatBytes() {
        var i = Math.floor(Math.log(this.props.bytes) / Math.log(1024));
        return !this.props.bytes && '0 Bytes' || (this.props.bytes / Math.pow(1024, i)).toFixed(2) + " " + ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'][i]
    },
    render () {
        return (
            <span>{ this.formatBytes() }</span>
        );
    }
});

업데이트
es6을 사용하는 사람들에게는 여기 동일한 구성 요소의 상태 비 저장 버전이 있습니다.

const sufixes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const getBytes = (bytes) => {
  const i = Math.floor(Math.log(bytes) / Math.log(1024));
  return !bytes && '0 Bytes' || (bytes / Math.pow(1024, i)).toFixed(2) + " " + sufixes[i];
};

const Bytes = ({ bytes }) => (<span>{ getBytes(bytes) }</span>);

Bytes.propTypes = {
  bytes: React.PropTypes.number,
};


답변

cocco 의 아이디어를 기반으로 , 여기에 덜 컴팩트하지만 더 포괄적 인 예가 있습니다.

<!DOCTYPE html>
<html>
<head>
<title>File info</title>

<script>
<!--
function fileSize(bytes) {
    var exp = Math.log(bytes) / Math.log(1024) | 0;
    var result = (bytes / Math.pow(1024, exp)).toFixed(2);

    return result + ' ' + (exp == 0 ? 'bytes': 'KMGTPEZY'[exp - 1] + 'B');
}

function info(input) {
    input.nextElementSibling.textContent = fileSize(input.files[0].size);
}
-->
</script>
</head>

<body>
<label for="upload-file"> File: </label>
<input id="upload-file" type="file" onchange="info(this)">
<div></div>
</body>
</html>