'Javascript Human Readable Filesize
I am currently trying to convert this php function to javascript:
function human_filesize($bytes, $decimals = 2) {
$sz = 'BKMGTP';
$factor = floor((strlen($bytes) - 1) / 3);
return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @$sz[$factor];
}
Here's what I have so Far:
function human_filesiz(bytes){
var decimals = 2;
var sz = 'BKMGTP';
var factor = Math.floor((bytes.length - 1) / 3);
return (bytes / Math.pow(1024, factor));
//return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @$sz[$factor];
}
Im Just struggling with the last line. Any Help Greatly Appreciated.
Solution 1:[1]
Based on the new international standards:
there are 2 ways now (SI & IEC)... or better 3 including the old one(JEDEC memory standards).
old standard (JEDEC & SI):
kB=1000, KB=1024
MB=1024=1000
GB=1024=1000
as you can see everything is messed up as you don't know if they are using 1024 or 1000 as multipler
https://wiki.ubuntu.com/UnitsPolicy
thats why we have this 2 new standards now:
Decimal (International System of Units [SI])
kB,MB,GB.. = 1000
Binary (International Electrotechnical Commission [IEC])
KiB,MiB,GiB.. = 1024
http://en.wikipedia.org/wiki/Binary_prefix
here are 2 functions i just wrote using shorthand and bitwise to make it fast & short.
function fileSizeSI(a,b,c,d,e){
return (b=Math,c=b.log,d=1000,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
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
fileSizeSI(5768374623);
//5.77 GB
fileSizeIEC(5768374623);
//5.37 GiB
EDIT
And here is a prototype for modern browsers that can handle both
Object.defineProperty(Number.prototype,'fileSize',{value:function(a,b,c,d){
return (a=a=='SI'?[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});
// default(IEC) KiB,MiB,GiB,TiB,PiB,EiB,ZiB,YiB
// (SI) kB,MB,GB,TB,PB,EB,ZB,YB
usage
(1289139173).fileSize(); // default Binary IEC
//1.20 GiB
(1289139173).fileSize('SI'); // Metric SI
//1.29 GB
i always used 1024 to calculate the size ... so i put the new IEC standard as default.
if you have some questions about the functions just ask
Solution 2:[2]
we should stop the loop when size exceeds what we have anticipated in the units array
function toHuman(size) {
var units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
var i = 0;
var j = units.length - 1;
while(size >= 1024 && i<j) {
size /= 1024;
++i;
}
return size.toFixed(1) + ' ' + units[i];
}
Solution 3:[3]
The answer by osi is great. If you want to understand what JS can do for your example though, you can take a look at this code which I made work for you:
function human_filesiz(bytes){
var decimals = 2;
var sz = 'BKMGTP';
bytesStr = new String(bytes);
var factor = Math.floor((bytesStr.length - 1) / 3);
// rounding the number in JS:
var number = bytes / Math.pow(1024, factor);
var roundPrecision = Math.pow(10, decimals);
number *= roundPrecision;
var result = Math.round(number, decimals) / roundPrecision;
result = result + sz.substring(factor, 1);
return result;
}
Solution 4:[4]
I like cocco's version.
I added rounding and locale conversion for the separators.
Object.defineProperty(Number.prototype, 'toFileSize', {
value: function(a, b, c, d){ return (a=a=='SI'?[1e3,'k','B']:[1024,'K','iB'],b=Math,c=b.log,d=c(this)/c(a[0])|0,+(b.round(this/b.pow(a[0],d)+"e+2")+"e-2")).toLocaleString()+' '+(d?(a[1]+'MGTPEZY')[--d]+a[2]:'Bytes');},
writable: false,
enumerable: false
});
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | |
| Solution 3 | Community |
| Solution 4 | Community |
