将文件大小以字节为单位转换为可读的string

我正在使用这个函数将文件大小以字节为单位转换为可读的文件大小:

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,例如,总是以二进制来衡量,所以表示1551859712就是〜1.4GiB是正确的。

另一方面,硬盘制造商喜欢使用小数,所以他们会把它称为1.6GB。

只是混淆,软盘使用两个系统的混合物 – 他们的1MB实际上是1024000字节。

这是我写的一个:

 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]; } 

例如

 humanFileSize(5000,true) > "5.0 kB" humanFileSize(5000,false) > "4.9 KiB" humanFileSize(-10000000000000000000000000000) > "-8271.8 YiB" 

计算的另一个实施例

 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]; }; 

这里是一个原型,将数字转换为可读的string,遵守新的国际标准。

有两种方法来表示大数字:您可以以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}); 

这个函数不包含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的幂


如果你只是想让他们中的一个在一个简短的线上function:

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 

用法:

 console.log(fileSizeIEC(7412834521)); 

如果你有关于function的一些问题就问

根据科科的想法,这里是一个不太紧凑,但希望更全面的例子。

 <!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> 
 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'; } 

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

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

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

作为ReactJS组件的解决scheme

 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() / 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, }; 
 1551859712 / 1024 = 1515488 1515488 / 1024 = 1479.96875 1479.96875 / 1024 = 1.44528198242188 

你的解决scheme是正确的 要实现的重要的事情是,为了从15518597121.5 ,你必须进行分割1000,但字节计数为二进制到十进制块1024,因此,技嘉值为什么less。

这里是我的 – 对于真正的大文件作品-_-

 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; } 

基于cocco的答案,但略微desugerified(说实话,我很舒服的是保持/添加),并没有显示尾随零,但仍然支持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>')); 

另一个类似于这里的例子

 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'; } 

它比其他具有类似特征的其他测量性能可以忽略不计。