Javascript 将文件大小(以字节为单位)转换为人类可读的字符串
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10420352/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Converting file size in bytes to human-readable string
提问by Hristo
I'm using this function to convert a file size in bytes to a human-readable file size:
我正在使用此函数将文件大小(以字节为单位)转换为人类可读的文件大小:
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];
};
However, it seems like this isn't 100% accurate. For example:
但是,这似乎不是 100% 准确。例如:
getReadableFileSizeString(1551859712); // output is "1.4 GB"
Shouldn't this be "1.5 GB"
? It seems like the division by 1024 is losing precision. Am I totally misunderstanding something or is there a better way to do this?
这不应该"1.5 GB"
吗?似乎除以 1024 正在失去精度。我是完全误解了什么还是有更好的方法来做到这一点?
采纳答案by Neil
It depends on whether you want to use the binary or decimal convention.
这取决于您要使用二进制还是十进制约定。
RAM, for instance, is always measured in binary, so to express 1551859712 as ~1.4GiB would be correct.
例如,RAM 总是以二进制表示,因此将 1551859712 表示为 ~1.4GiB 是正确的。
On the other hand, hard disk manufacturers like to use decimal, so they would call it ~1.6GB.
另一方面,硬盘制造商喜欢使用十进制,因此他们将其称为~1.6GB。
And just to be confusing, floppy disks use a mixture of the two systems - their 1MB is actually 1024000 bytes.
令人困惑的是,软盘混合使用了这两种系统——它们的 1MB 实际上是 1024000 字节。
回答by mpen
Here's one I wrote:
这是我写的一篇:
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
回答by Andrew V.
Another embodiment of the calculation
计算的另一个实施例
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];
};
回答by cocco
Here is a prototype to convert a number to a readable string respecting the new international standards.
这是一个将数字转换为符合新国际标准的可读字符串的原型。
There are two ways to represent big numbers: You could either display them in multiples of 1000 = 10 3 (base 10) or 1024 = 2 10 (base 2). If you divide by 1000, you probably use the SI prefix names, if you divide by 1024, you probably use the IEC prefix names. The problem starts with dividing by 1024. Many applications use the SI prefix names for it and some use the IEC prefix names. The current situation is a mess. If you see SI prefix names you do not know whether the number is divided by 1000 or 1024
有两种表示大数字的方法:您可以以 1000 = 10 3(基数 10)或 1024 = 2 10(基数 2)的倍数显示它们。如果除以 1000,则可能使用 SI 前缀名称,如果除以 1024,则可能使用 IEC 前缀名称。问题从除以 1024 开始。许多应用程序使用 SI 前缀名称,有些应用程序使用 IEC 前缀名称。目前的情况是一团糟。如果您看到 SI 前缀名称,您不知道该数字是除以 1000 还是 1024
https://wiki.ubuntu.com/UnitsPolicy
https://wiki.ubuntu.com/UnitsPolicy
http://en.wikipedia.org/wiki/Template:Quantities_of_bytes
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});
This function contains no loop
, and so it's probably faster than some other functions.
此函数包含 no loop
,因此它可能比其他一些函数更快。
Usage:
用法:
IEC prefix
IEC前缀
console.log((186457865).fileSize()); // default IEC (power 1024)
//177.82 MiB
//KiB,MiB,GiB,TiB,PiB,EiB,ZiB,YiB
SI prefix
SI前缀
console.log((186457865).fileSize(1)); //1,true for SI (power 1000)
//186.46 MB
//kB,MB,GB,TB,PB,EB,ZB,YB
i set the IEC as default because i always used binary mode to calculate the size of a file... using the power of 1024
我将 IEC 设置为默认值,因为我总是使用二进制模式来计算文件的大小...使用 1024 的幂
If you just want one of them in a short oneliner function:
如果您只想在简短的 oneliner 函数中使用其中之一:
SI
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
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
Usage:
用法:
console.log(fileSizeIEC(7412834521));
if you have some questions about the functions just ask
如果您对功能有一些疑问,请询问
回答by Joshaven Potter
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.91 GB"sizeOf(7054110);
//=> "6.73 MB"sizeOf( (3*1024*1024) );
//=> "3.00 MB"
大小(2054110009);
//=> "1.91 GB"大小(7054110);
//=> "6.73 MB"sizeOf((3*1024*1024));
//=> "3.00 MB"
回答by Patrick Mencias-lewis
Solution as ReactJS Component
作为 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>
);
}
});
UPDATEFor those using es6 here is a stateless version of this same component
更新对于那些使用 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,
};
回答by KitKat
Based on cocco's idea, here's a less compact -but hopefully more comprehensive- example.
基于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>
回答by Nick Kuznia
Another example similar to those here
另一个类似于此处的示例
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';
}
It measures negligibly better performance than the others with similar features.
它测量的性能比具有类似特征的其他性能好得可以忽略不计。
回答by Camilo Martin
I wanted the "file manager" behavior (e.g., Windows Explorer) where the number of decimal places is proportional to the number size. Seemingly none of the other answers does this.
我想要“文件管理器”行为(例如,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`
}
Here's some examples:
下面是一些例子:
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"
回答by Ebrahim Byagowi
Based on cocco's answerbut slightly desugerified (honestly, ones I was comfortable with are remained/added) and doesn't show trailing zeros but still supports 0, hope to be useful for others:
基于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>'));