将文件大小以字节为单位转换为人类可读的字符串

Hri*_*sto 223 javascript filesize human-readable

我正在使用此函数将文件大小(以字节为单位)转换为人类可读的文件大小:

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];
};
Run Code Online (Sandbox Code Playgroud)

但是,似乎这并非100%准确.例如:

getReadableFileSizeString(1551859712); // output is "1.4 GB"
Run Code Online (Sandbox Code Playgroud)

不应该这样"1.5 GB"吗?似乎1024的划分正在失去精度.我完全误解了某些东西,还是有更好的方法来做到这一点?

mpe*_*pen 315

这是我写的一个:

function humanFileSize(bytes, si) {
    var thresh = si ? 1000 : 1024;
    if(Math.abs(bytes) < thresh) {
        return bytes + ' B';
    }
    var units = si
        ? ['kB','MB','GB','TB','PB','EB','ZB','YB']
        : ['KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB'];
    var u = -1;
    do {
        bytes /= thresh;
        ++u;
    } while(Math.abs(bytes) >= thresh && u < units.length - 1);
    return bytes.toFixed(1)+' '+units[u];
}
Run Code Online (Sandbox Code Playgroud)

例如

humanFileSize(5000,true)
> "5.0 kB"
humanFileSize(5000,false)
> "4.9 KiB"
humanFileSize(-10000000000000000000000000000)
> "-8271.8 YiB"
Run Code Online (Sandbox Code Playgroud)

  • @AaronBlenkush:你什么时候会有一个负文件大小? (15认同)
  • 我刚刚将您的功能复制到Google Sheet中,我用它来显示"清理"操作后的大小增量.之前,之后和差异.清理操作导致一些数据库表的增长,以及其他数据库表的减少.例如,表A的diff为-1.95 MB,而表B的diff为500 kB.因此:积极和消极:-) (9认同)
  • 我正在做一个调整:评估阈值时,取绝对值。这样,该函数将支持负值。不错的功能!感谢您没有使用 switch 语句!! (2认同)
  • @兰德斯00:感谢缩小版本。不过,你能告诉我,为什么在 *E* oft *EiB* 之后插入两个不可见的 Unicode 字符 U+200C(零宽度非连接器)和 U+200B(零宽度空间)?这是否打算作为水印,以便您可以跟踪谁使用了此代码?如果是这样,我认为你应该在你的帖子中做到这一点。 (2认同)
  • @Leviathan我不是故意插入它们的。我刚刚通过 UglifyJS 运行它并将其粘贴到这里,所以我不确定为什么这些字符甚至在那里...... (2认同)
  • @vee 小数位。您可以在底部看到一些具有不同数字的示例。我将使用文档注释更新代码。 (2认同)

小智 76

计算的另一个实施例

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];
};
Run Code Online (Sandbox Code Playgroud)

  • 将第一行更改为`var i = size == 0?0:Math.floor(Math.log(size)/ Math.log(1024));如果它为0,它似乎就可以了.它会返回"0 B". (10认同)
  • 似乎不处理0 (8认同)
  • 它处理或不处理0?毕竟,这与if(size == 0){} else {}仍然比我见过的大多数更优雅. (4认同)
  • “*1”将数据类型从字符串更改为数字,因此对于值“1024”,您将得到“1 kB”而不是“1.00 kB”。您可以通过执行“Number((size / Math.pow(1024, i)).toFixed(2))”来完成同样的事情,从而使 TypeScript 满意。 (3认同)
  • 仅供参考;我知道答案是纯 JavaScript,但如果有人不想在 TypeScript 中使用它,它就不起作用(输入不正确,因为你正在执行“toFixed”,然后用字符串进行数学运算。“ * 1` 做吗? (2认同)

Nei*_*eil 41

这取决于您是否要使用二进制或十进制约定.

例如,RAM总是以二进制形式测量,因此将1551859712表示为~1.4GiB是正确的.

另一方面,硬盘制造商喜欢使用小数,因此他们称之为~1.6GB.

而且令人困惑的是,软盘使用两种系统的混合 - 它们的1MB实际上是1024000字节.

  • 晚餐有趣;-)"只是令人困惑,软盘使用两个系统的混合 - 他们的1MB实际上是1024000字节." (3认同)
  • 确实,RAM 大小使用 IEC 单位测量,磁盘大小使用公制测量。有一个同构 npm 模块可以转换两者:[byte-size](https://github.com/75lb/byte-size) (2认同)

coc*_*cco 39

这是一个将数字转换为符合新国际标准的可读字符串的原型.

有两种表示大数字的方法:您可以以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});
Run Code Online (Sandbox Code Playgroud)

此函数包含no loop,因此它可能比其他一些函数更快.

用法:

IEC前缀

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

SI前缀

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

我将IEC设置为默认值,因为我总是使用二进制模式来计算文件的大小...使用1024的幂


如果您只想在短的oneliner函数中使用其中一个:

SI

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

用法:

console.log(fileSizeIEC(7412834521));
Run Code Online (Sandbox Code Playgroud)

如果您对这些功能有疑问,请询问

  • 缩小应该是构建过程的一部分,而不是编码风格.没有认真的开发人员会因此而使用此代码,因为阅读和验证正确性需要很长时间. (14认同)

Jos*_*ter 20

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';
}
Run Code Online (Sandbox Code Playgroud)

整型尺寸(2054110009);
// =>"1.91 GB"

整型尺寸(7054110);
// =>"6.73 MB"

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

  • 如果要摆脱多余的字节空间,可以使用零宽度的空间\ u200b:'\ u200bKMGTP'。 (2认同)

Pat*_*wis 15

作为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>
        );
    }
});
Run Code Online (Sandbox Code Playgroud)

更新 对于那些使用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,
};
Run Code Online (Sandbox Code Playgroud)


Kit*_*Kat 12

根据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> 
Run Code Online (Sandbox Code Playgroud)


Jam*_*udd 10

这里有很多很棒的答案。但是,如果您正在寻找一种非常简单的方法,并且您不介意流行的库,那么一个很好的解决方案是filesize https://www.npmjs.com/package/filesize

它有很多选项并且用法很简单,例如

filesize(265318); // "259.1 KB"
Run Code Online (Sandbox Code Playgroud)

取自他们的优秀例子


mpe*_*pen 9

这是另一个国际化的实现,用 TypeScript 编写:

\n
const UNITS = [\'byte\', \'kilobyte\', \'megabyte\', \'gigabyte\', \'terabyte\', \'petabyte\']\nconst BYTES_PER_KB = 1000\n\n\n/**\n * Format bytes as human-readable text.\n *\n * @param sizeBytes Number of bytes.\n *\n * @return Formatted string.\n */\nexport function humanFileSize(sizeBytes: number | bigint): string {\n    let size = Math.abs(Number(sizeBytes))\n\n    let u = 0\n    while(size >= BYTES_PER_KB && u < UNITS.length-1) {\n        size /= BYTES_PER_KB\n        ++u\n    }\n\n    return new Intl.NumberFormat([], {\n        style: \'unit\',\n        unit: UNITS[u],\n        unitDisplay: \'short\',\n        maximumFractionDigits: 1,\n    }).format(size)\n}\n
Run Code Online (Sandbox Code Playgroud)\n

替换[]为语言代码,例如fr强制本地化而不是默认值。

\n
console.log(humanFileSize(0))\nconsole.log(humanFileSize(9))\nconsole.log(humanFileSize(99))\nconsole.log(humanFileSize(999))\nconsole.log(humanFileSize(1000))\nconsole.log(humanFileSize(1001))\nconsole.log(humanFileSize(1023))\nconsole.log(humanFileSize(1024))\nconsole.log(humanFileSize(1025))\nconsole.log(humanFileSize(100_000))\nconsole.log(humanFileSize(1_000_000))\nconsole.log(humanFileSize(1_000_000_000))\nconsole.log(humanFileSize(1_000_000_000_000))\nconsole.log(humanFileSize(1_000_000_000_000_000))\nconsole.log(humanFileSize(1_000_000_000_000_000_000))\n
Run Code Online (Sandbox Code Playgroud)\n
// fr\n0\xe2\x80\xafo\n9\xe2\x80\xafo\n99\xe2\x80\xafo\n999\xe2\x80\xafo\n1\xe2\x80\xafko\n1\xe2\x80\xafko\n1\xe2\x80\xafko\n1\xe2\x80\xafko\n1\xe2\x80\xafko\n100\xe2\x80\xafko\n1\xe2\x80\xafMo\n1\xe2\x80\xafGo\n1\xe2\x80\xafTo\n1\xe2\x80\xafPo\n1\xe2\x80\xaf000\xe2\x80\xafPo\n\n// en-US\n0 byte\n9 byte\n99 byte\n999 byte\n1 kB\n1 kB\n1 kB\n1 kB\n1 kB\n100 kB\n1 MB\n1 GB\n1 TB\n1 PB\n1,000 PB\n
Run Code Online (Sandbox Code Playgroud)\n
\n

您现在可以Intl.NumberFormat自动为您进行单位转换。例如

\n

\r\n
\r\n
const UNITS = [\'byte\', \'kilobyte\', \'megabyte\', \'gigabyte\', \'terabyte\', \'petabyte\']\nconst BYTES_PER_KB = 1000\n\n\n/**\n * Format bytes as human-readable text.\n *\n * @param sizeBytes Number of bytes.\n *\n * @return Formatted string.\n */\nexport function humanFileSize(sizeBytes: number | bigint): string {\n    let size = Math.abs(Number(sizeBytes))\n\n    let u = 0\n    while(size >= BYTES_PER_KB && u < UNITS.length-1) {\n        size /= BYTES_PER_KB\n        ++u\n    }\n\n    return new Intl.NumberFormat([], {\n        style: \'unit\',\n        unit: UNITS[u],\n        unitDisplay: \'short\',\n        maximumFractionDigits: 1,\n    }).format(size)\n}\n
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n

...但是单位有点奇怪。例如1024**41.1BB我猜是“十亿字节”;我认为没有人使用过它,即使它在技术上是正确的。

\n


Ker*_*uch 6

我的回答可能会晚一些,但我想这会对某人有所帮助。

公制前缀:

/**
 * Format file size in metric prefix
 * @param fileSize
 * @returns {string}
 */
const formatFileSizeMetric = (fileSize) => {
  let size = Math.abs(fileSize);

  if (Number.isNaN(size)) {
    return 'Invalid file size';
  }

  if (size === 0) {
    return '0 bytes';
  }

  const units = ['bytes', 'kB', 'MB', 'GB', 'TB'];
  let quotient = Math.floor(Math.log10(size) / 3);
  quotient = quotient < units.length ? quotient : units.length - 1;
  size /= (1000 ** quotient);

  return `${+size.toFixed(2)} ${units[quotient]}`;
};
Run Code Online (Sandbox Code Playgroud)

二进制前缀:

/**
 * Format file size in binary prefix
 * @param fileSize
 * @returns {string}
 */
const formatFileSizeBinary = (fileSize) => {
  let size = Math.abs(fileSize);

  if (Number.isNaN(size)) {
    return 'Invalid file size';
  }

  if (size === 0) {
    return '0 bytes';
  }

  const units = ['bytes', 'kiB', 'MiB', 'GiB', 'TiB'];
  let quotient = Math.floor(Math.log2(size) / 10);
  quotient = quotient < units.length ? quotient : units.length - 1;
  size /= (1024 ** quotient);

  return `${+size.toFixed(2)} ${units[quotient]}`;
};
Run Code Online (Sandbox Code Playgroud)

例子:

// Metrics prefix
formatFileSizeMetric(0)      // 0 bytes
formatFileSizeMetric(-1)     // 1 bytes
formatFileSizeMetric(100)    // 100 bytes
formatFileSizeMetric(1000)   // 1 kB
formatFileSizeMetric(10**5)  // 10 kB
formatFileSizeMetric(10**6)  // 1 MB
formatFileSizeMetric(10**9)  // 1GB
formatFileSizeMetric(10**12) // 1 TB
formatFileSizeMetric(10**15) // 1000 TB

// Binary prefix
formatFileSizeBinary(0)     // 0 bytes
formatFileSizeBinary(-1)    // 1 bytes
formatFileSizeBinary(1024)  // 1 kiB
formatFileSizeBinary(2048)  // 2 kiB
formatFileSizeBinary(2**20) // 1 MiB
formatFileSizeBinary(2**30) // 1 GiB
formatFileSizeBinary(2**40) // 1 TiB
formatFileSizeBinary(2**50) // 1024 TiB
Run Code Online (Sandbox Code Playgroud)


fif*_*ffy 5

这是我的 - 适用于非常大的文件-_-

function formatFileSize(size)
{
    var sizes = [' Bytes', ' KB', ' MB', ' GB', ' TB', ' PB', ' EB', ' ZB', ' YB'];
    for (var i = 1; i < sizes.length; i++)
    {
        if (size < Math.pow(1024, i)) return (Math.round((size/Math.pow(1024, i-1))*100)/100) + sizes[i-1];
    }
    return size;
}
Run Code Online (Sandbox Code Playgroud)

  • 那不要用它.它只是客户端cpu使用,所以谁在乎;) (2认同)
  • @fiffy 好吧,客户端 CPU 也很宝贵,尤其是在移动设备和复杂的应用程序上。:) (2认同)

Ebr*_*owi 5

根据cocco的回答,但略微不加修饰(老实说,我感到满意的那些保持/增加),并且不显示尾随零但仍支持0,希望对其他人有用:

function fileSizeSI(size) {
    var e = (Math.log(size) / Math.log(1e3)) | 0;
    return +(size / Math.pow(1e3, e)).toFixed(2) + ' ' + ('kMGTPEZY'[e - 1] || '') + 'B';
}


// test:
document.write([0, 23, 4322, 324232132, 22e9, 64.22e12, 76.22e15, 64.66e18, 77.11e21, 22e24].map(fileSizeSI).join('<br>'));
Run Code Online (Sandbox Code Playgroud)


Nic*_*nia 5

另一个类似于这里的例子

function fileSize(b) {
    var u = 0, s=1024;
    while (b >= s || -b >= s) {
        b /= s;
        u++;
    }
    return (u ? b.toFixed(1) + ' ' : b) + ' KMGTPEZY'[u] + 'B';
}
Run Code Online (Sandbox Code Playgroud)

与具有类似功能的其他产品相比,它的性能可忽略不计。


Cam*_*tin 5

我想要“文件管理器”行为(例如Windows资源管理器),其中小数位数与数字大小成正比。似乎没有其他答案可以做到这一点。

function humanFileSize(size) {
    if (size < 1024) return size + ' B'
    let i = Math.floor(Math.log(size) / Math.log(1024))
    let num = (size / Math.pow(1024, i))
    let round = Math.round(num)
    num = round < 10 ? num.toFixed(2) : round < 100 ? num.toFixed(1) : round
    return `${num} ${'KMGTPEZY'[i-1]}B`
}
Run Code Online (Sandbox Code Playgroud)

这里有一些例子:

humanFileSize(0)          // "0 B"
humanFileSize(1023)       // "1023 B"
humanFileSize(1024)       // "1.00 KB"
humanFileSize(10240)      // "10.0 KB"
humanFileSize(102400)     // "100 KB"
humanFileSize(1024000)    // "1000 KB"
humanFileSize(12345678)   // "11.8 MB"
humanFileSize(1234567890) // "1.15 GB"
Run Code Online (Sandbox Code Playgroud)


Moh*_*fei 5

SI 系统的简单而简短的“Pretty Bytes”函数,无需进行不必要的小数舍入。

事实上,因为数字大小应该是人类可读的,所以“千分之一”的显示不再是人类可读的。

小数位数默认为 2,但可以在调用函数时将其修改为其他值。常见的大多显示是默认2位小数。

代码很短,并且使用了数字字符串三元组的方法。

// Simple Pretty Bytes with SI system
// Without fraction rounding

function numberPrettyBytesSI(Num=0, dec=2){
if (Num<1000) return Num+" Bytes";
Num =("0".repeat((Num+="").length*2%3)+Num).match(/.{3}/g);
return Number(Num[0])+"."+Num[1].substring(0,dec)+" "+"  kMGTPEZY"[Num.length]+"B";
}

console.log(numberPrettyBytesSI(0));
console.log(numberPrettyBytesSI(500));
console.log(numberPrettyBytesSI(1000));
console.log(numberPrettyBytesSI(15000));
console.log(numberPrettyBytesSI(12345));
console.log(numberPrettyBytesSI(123456));
console.log(numberPrettyBytesSI(1234567));
console.log(numberPrettyBytesSI(12345678));
Run Code Online (Sandbox Code Playgroud)


小智 5

从 2020 年开始,您可以使用文件大小的 npm 包,该包支持 IEC(功率 1024,默认值)、SI(功率 1000)和 JEDEC(替代 SI 单位表示法)格式。

npm install file-size

import filesize from "filesize";

// outputs: 186.46 MB
filesize(186457865).human('si');

// outputs: 177.82 MiB
filesize(186457865).human();
Run Code Online (Sandbox Code Playgroud)

https://www.npmjs.com/package/file-size

  • 注意:这个库 `file-size` 很少被使用,并且没有得到真正的支持(最后一个版本是在 7 年前)。建议从我的答案中查看“文件大小”/sf/answers/4558683111/ (3认同)