admin管理员组文章数量:1126318
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 /= 1024;
i++;
} while (fileSizeInBytes > 1024);
return Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i];
}
console.log(getReadableFileSizeString(1551859712)); // output is "1.4 GB"
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 /= 1024;
i++;
} while (fileSizeInBytes > 1024);
return Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i];
}
console.log(getReadableFileSizeString(1551859712)); // output is "1.4 GB"
However, it seems like this isn't 100% accurate. For example:
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?
25 Answers
Reset to default 592Here's one I wrote:
/**
* Format bytes as human-readable text.
*
* @param bytes Number of bytes.
* @param si True to use metric (SI) units, aka powers of 1000. False to use
* binary (IEC), aka powers of 1024.
* @param dp Number of decimal places to display.
*
* @return Formatted string.
*/
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(1551859712)) // 1.4 GiB
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
Another embodiment of the calculation
function humanFileSize(size) {
var i = size == 0 ? 0 : Math.floor(Math.log(size) / Math.log(1024));
return +((size / Math.pow(1024, i)).toFixed(2)) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i];
}
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.
On the other hand, hard disk manufacturers like to use decimal, so they would call it ~1.6GB.
And just to be confusing, floppy disks use a mixture of the two systems - their 1MB is actually 1024000 bytes.
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
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});
This function contains no loop
, and so it's probably faster than some other functions.
Usage:
IEC prefix
console.log((186457865).fileSize()); // default IEC (power 1024)
//177.82 MiB
//KiB,MiB,GiB,TiB,PiB,EiB,ZiB,YiB
SI prefix
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
If you just want one of them in a short oneliner 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
Usage:
console.log(fileSizeIEC(7412834521));
if you have some questions about the functions just ask
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"
Solution as ReactJS Component
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>
);
}
});
UPDATE For those using es6 here is a stateless version of this same component
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,
};
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.
Here's another implementation, internationalized, written in TypeScript:
const UNITS = ['byte', 'kilobyte', 'megabyte', 'gigabyte', 'terabyte', 'petabyte']
const BYTES_PER_KB = 1000
/**
* Format bytes as human-readable text.
*
* @param sizeBytes Number of bytes.
*
* @return Formatted string.
*/
export function humanFileSize(sizeBytes: number | bigint): string {
let size = Math.abs(Number(sizeBytes))
let u = 0
while(size >= BYTES_PER_KB && u < UNITS.length-1) {
size /= BYTES_PER_KB
++u
}
return new Intl.NumberFormat([], {
style: 'unit',
unit: UNITS[u],
unitDisplay: 'short',
maximumFractionDigits: 1,
}).format(size)
}
Replace []
with a language code like fr
to force a localization other than the default.
console.log(humanFileSize(0))
console.log(humanFileSize(9))
console.log(humanFileSize(99))
console.log(humanFileSize(999))
console.log(humanFileSize(1000))
console.log(humanFileSize(1001))
console.log(humanFileSize(1023))
console.log(humanFileSize(1024))
console.log(humanFileSize(1025))
console.log(humanFileSize(100_000))
console.log(humanFileSize(1_000_000))
console.log(humanFileSize(1_000_000_000))
console.log(humanFileSize(1_000_000_000_000))
console.log(humanFileSize(1_000_000_000_000_000))
console.log(humanFileSize(1_000_000_000_000_000_000))
// fr
0 o
9 o
99 o
999 o
1 ko
1 ko
1 ko
1 ko
1 ko
100 ko
1 Mo
1 Go
1 To
1 Po
1 000 Po
// en-US
0 byte
9 byte
99 byte
999 byte
1 kB
1 kB
1 kB
1 kB
1 kB
100 kB
1 MB
1 GB
1 TB
1 PB
1,000 PB
You can get Intl.NumberFormat
to do the unit conversion for you automatically now. e.g.
const sizeFormatter = new Intl.NumberFormat([], {
style: 'unit',
unit: 'byte',
notation: "compact",
unitDisplay: "narrow",
})
console.log(sizeFormatter.format(0))
console.log(sizeFormatter.format(1))
console.log(sizeFormatter.format(999))
console.log(sizeFormatter.format(1000))
console.log(sizeFormatter.format(1023))
console.log(sizeFormatter.format(1024))
console.log(sizeFormatter.format(1024**2))
console.log(sizeFormatter.format(1024**3))
console.log(sizeFormatter.format(1024**4))
console.log(sizeFormatter.format(1024**5))
console.log(sizeFormatter.format(1024**6))
...but the units are kinda weird. e.g. 1024**4
is 1.1BB
which I guess is "billion bytes"; I don't think anyone ever uses that even if it's technically correct.
Based on cocco's idea, here's a less compact -but hopefully more comprehensive- example.
<!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>
There are lots of great answers here. But if your looking for a really simple way, and you don't mind a popular library, a great solution is filesize
https://www.npmjs.com/package/filesize
It has lots of options and the usage is simple e.g.
filesize(265318); // "259.1 KB"
Taken from their excellent examples
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.
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"
As of 2020, you can use file-size npm package, that supports formatting in IEC (power 1024, default), SI (power 1000), and JEDEC (Alternative SI Unit Notation).
npm install file-size
import filesize from "filesize";
// outputs: 186.46 MB
filesize(186457865).human('si');
// outputs: 177.82 MiB
filesize(186457865).human();
https://www.npmjs.com/package/file-size
My answer might be late, but I guess it will help someone.
Metric prefix:
/**
* 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]}`;
};
Binary prefix:
/**
* 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]}`;
};
Examples:
// 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
A simple and short "Pretty Bytes" function for the SI system without the unnecessary fractionals rounding.
In fact, because the number size is supposed to be human-readable, a "1 of a thousand fraction" display is no longer human.
The number of decimal places is defaulted to 2 but can be modified on calling the function to other values. The common mostly display is the default 2 decimal place.
The code is short and uses the method of Number String Triplets.
// 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));
Here's mine - works for really big files too -_-
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;
}
Based on cocco's answer but 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:
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>'));
1551859712 / 1024 = 1515488
1515488 / 1024 = 1479.96875
1479.96875 / 1024 = 1.44528198242188
Your solution is correct. The important thing to realize is that in order to get from 1551859712
to 1.5
, you have to do divisions by 1000, but bytes are counted in binary-to-decimal chunks of 1024, hence why the Gigabyte value is less.
i'm just 10 years late! for es6
function humanReadableSize(bytes) {
let size = parseInt(data)
for (let unit of ['b', 'Kb', 'Mb', 'Gb']) {
if (size < 1024) return `${size.toFixed(2)} ${unit}`
size /= 1024.0
}
}
I found @cocco's answer interesting, but had the following issues with it:
- Don't modify native types or types you don't own
- Write clean, readable code for humans, let minifiers optimize code for machines
- (Bonus for TypeScript users) Doesn't play well with TypeScript
TypeScript:
/**
* Describes manner by which a quantity of bytes will be formatted.
*/
enum ByteFormat {
/**
* Use Base 10 (1 kB = 1000 bytes). Recommended for sizes of files on disk, disk sizes, bandwidth.
*/
SI = 0,
/**
* Use Base 2 (1 KiB = 1024 bytes). Recommended for RAM size, size of files on disk.
*/
IEC = 1
}
/**
* Returns a human-readable representation of a quantity of bytes in the most reasonable unit of magnitude.
* @example
* formatBytes(0) // returns "0 bytes"
* formatBytes(1) // returns "1 byte"
* formatBytes(1024, ByteFormat.IEC) // returns "1 KiB"
* formatBytes(1024, ByteFormat.SI) // returns "1.02 kB"
* @param size The size in bytes.
* @param format Format using SI (Base 10) or IEC (Base 2). Defaults to SI.
* @returns A string describing the bytes in the most reasonable unit of magnitude.
*/
function formatBytes(
value: number,
format: ByteFormat = ByteFormat.SI
) {
const [multiple, k, suffix] = (format === ByteFormat.SI
? [1000, 'k', 'B']
: [1024, 'K', 'iB']) as [number, string, string]
// tslint:disable-next-line: no-bitwise
const exp = (Math.log(value) / Math.log(multiple)) | 0
// or, if you'd prefer not to use bitwise expressions or disabling tslint rules, remove the line above and use the following:
// const exp = value === 0 ? 0 : Math.floor(Math.log(value) / Math.log(multiple))
const size = Number((value / Math.pow(multiple, exp)).toFixed(2))
return (
size +
' ' +
(exp
? (k + 'MGTPEZY')[exp - 1] + suffix
: 'byte' + (size !== 1 ? 's' : ''))
)
}
// example
[0, 1, 1024, Math.pow(1024, 2), Math.floor(Math.pow(1024, 2) * 2.34), Math.pow(1024, 3), Math.floor(Math.pow(1024, 3) * 892.2)].forEach(size => {
console.log('Bytes: ' + size)
console.log('SI size: ' + formatBytes(size))
console.log('IEC size: ' + formatBytes(size, 1) + '\n')
});
This is size improvement of mpen answer
function humanFileSize(bytes, si=false) {
let u, b=bytes, t= si ? 1000 : 1024;
['', si?'k':'K', ...'MGTPEZY'].find(x=> (u=x, b/=t, b**2<1));
return `${u ? (t*b).toFixed(1) : bytes} ${u}${!si && u ? 'i':''}B`;
}
function humanFileSize(bytes, si=false) {
let u, b=bytes, t= si ? 1000 : 1024;
['', si?'k':'K', ...'MGTPEZY'].find(x=> (u=x, b/=t, b**2<1));
return `${u ? (t*b).toFixed(1) : bytes} ${u}${!si && u ? 'i':''}B`;
}
// TEST
console.log(humanFileSize(5000)); // 4.9 KiB
console.log(humanFileSize(5000,true)); // 5.0 kB
The typescript version to @Andrew V answer with the new "Template Literal Types"
export const humanFileSize = (bytes: number): `${number} ${'B' | 'KB' | 'MB' | 'GB' | 'TB'}` => {
const index = Math.floor(Math.log(bytes) / Math.log(1024));
return `${Number((bytes / Math.pow(1024, index)).toFixed(2)) * 1} ${(['B', 'KB', 'MB', 'GB', 'TB'] as const)[index]}`;
};
For those who use Angular
, there's a package called angular-pipes
that has a pipe for this:
File
import { BytesPipe } from 'angular-pipes';
Usage
{{ 150 | bytes }} <!-- 150 B -->
{{ 1024 | bytes }} <!-- 1 KB -->
{{ 1048576 | bytes }} <!-- 1 MB -->
{{ 1024 | bytes: 0 : 'KB' }} <!-- 1 MB -->
{{ 1073741824 | bytes }} <!-- 1 GB -->
{{ 1099511627776 | bytes }} <!-- 1 TB -->
{{ 1073741824 | bytes : 0 : 'B' : 'MB' }} <!-- 1024 MB -->
Link to the docs.
To have the number of decimals dynamically adjusted in the voted solution, convert the bytes.toFixed(dp)
to number and then back to string like this:
return Number(bytes.toFixed(dp)).toString() + " " + units[u];
This will show 100 GiB instead of 100.00 GiB. Reference to question toFixed() dynamically in js
I wrote a size conversion function that also accepts human readable formats.
JS
const bitBase = 8;
const suffixes = {
bit: 'b',
b: 'B',
kb: 'KB',
mb: 'MB',
gb: 'GB',
tb: 'TB',
};
const multipliers = {
bit: {
toBitHr: 1,
toB: 1 / bitBase,
toKB: 1 / (bitBase * 1e3),
toMB: 1 / (bitBase * 1e6),
toGB: 1 / (bitBase * 1e9),
toTB: 1 / (bitBase * 1e12),
},
B: {
toBit: bitBase,
toBHr: 1,
toKB: 1 / 1e3,
toMB: 1 / 1e6,
toGB: 1 / 1e9,
toTB: 1 / 1e12,
},
KB: {
toBit: 1 / (bitBase * 1e3),
toB: 1e3,
toKBHr: 1,
toMB: 1 / 1e3,
toGB: 1 / 1e6,
toTB: 1 / 1e9,
},
MB: {
toBit: bitBase * 1e6,
toB: 1e6,
toKB: 1e3,
toMBHr: 1,
toGB: 1 / 1e3,
toTB: 1 / 1e6,
},
GB: {
toBit: bitBase * 1e9,
toB: 1e9,
toKB: 1e6,
toMB: 1e3,
toGBHr: 1,
toTB: 1 / 1e3,
},
TB: {
toBit: bitBase * 1e12,
toB: 1e12,
toKB: 1e9,
toMB: 1e6,
toGB: 1e3,
toTBHr: 1,
},
};
const round = (num, decimalPlaces) => {
const strNum = num.toString();
const isExp = strNum.includes('e');
if (isExp) {
return Number(num.toPrecision(decimalPlaces + 1));
}
return Number(
`${Math.round(Number(`${num}e${decimalPlaces}`))}e${decimalPlaces * -1}`,
);
};
function conv(
value,
hr,
rnd,
multiplier,
suffix,
) {
let val = value * multiplier;
if ((value * multiplier) > Number.MAX_SAFE_INTEGER) {
val = Number.MAX_SAFE_INTEGER;
}
if (val < Number.MIN_VALUE) val = 0;
if ((rnd || rnd === 0) && val < Number.MAX_SAFE_INTEGER) {
val = round(val, rnd);
}
if (hr) return `${val}${suffix}`;
return val;
}
const MemConv = (function _() {
return {
bit(value) {
return {
toBitHr(opts = {}) {
return conv(
value,
true,
opts.round || false,
multipliers.bit.toBitHr,
suffixes.bit,
);
},
toB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.bit.toB,
suffixes.b,
);
},
toKB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.bit.toKB,
suffixes.kb,
);
},
toMB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.bit.toMB,
suffixes.mb,
);
},
toGB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.bit.toGB,
suffixes.gb,
);
},
toTB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.bit.toTB,
suffixes.tb,
);
},
};
},
B(value) {
return {
toBit(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.B.toBit,
suffixes.bit,
);
},
toBHr(opts = {}) {
return conv(
value,
true,
opts.round || false,
multipliers.B.toBHr,
suffixes.b,
);
},
toKB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.B.toKB,
suffixes.kb,
);
},
toMB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.B.toMB,
suffixes.mb,
);
},
toGB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.B.toGB,
suffixes.gb,
);
},
toTB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.B.toTB,
suffixes.tb,
);
},
};
},
KB(value) {
return {
toBit(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.KB.toBit,
suffixes.bit,
);
},
toB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.KB.toB,
suffixes.b,
);
},
toKBHr(opts = {}) {
return conv(
value,
true,
opts.round || false,
multipliers.KB.toKBHr,
suffixes.kb,
);
},
toMB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.KB.toMB,
suffixes.mb,
);
},
toGB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.KB.toGB,
suffixes.gb,
);
},
toTB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.KB.toTB,
suffixes.tb,
);
},
};
},
MB(value) {
return {
toBit(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.MB.toBit,
suffixes.bit,
);
},
toB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.MB.toB,
suffixes.b,
);
},
toKB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.MB.toKB,
suffixes.kb,
);
},
toMBHr(opts = {}) {
return conv(
value,
true,
opts.round || false,
multipliers.MB.toMBHr,
suffixes.mb,
);
},
toGB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.MB.toGB,
suffixes.gb,
);
},
toTB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.MB.toTB,
suffixes.tb,
);
},
};
},
GB(value) {
return {
toBit(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.GB.toBit,
suffixes.bit,
);
},
toB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.GB.toB,
suffixes.b,
);
},
toKB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.GB.toKB,
suffixes.kb,
);
},
toMB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.GB.toMB,
suffixes.mb,
);
},
toGBHr(opts = {}) {
return conv(
value,
true,
opts.round || false,
multipliers.GB.toGBHr,
suffixes.gb,
);
},
toTB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.GB.toTB,
suffixes.tb,
);
},
};
},
TB(value) {
return {
toBit(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.TB.toBit,
suffixes.bit,
);
},
toB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.TB.toB,
suffixes.b,
);
},
toKB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.TB.toKB,
suffixes.kb,
);
},
toMB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.TB.toMB,
suffixes.mb,
);
},
toGB(opts = {}) {
return conv(
value,
opts.hr || false,
opts.round || false,
multipliers.TB.toGB,
suffixes.gb,
);
},
toTBHr(opts = {}) {
return conv(
value,
true,
opts.round || false,
multipliers.TB.toTBHr,
suffixes.tb,
);
},
};
},
};
}());
const testCases = [1, 10, 150, 1000, 74839.67346];
const HRSuffixes = Object.values(suffixes);
const roundDecimals = 2;
const precision = Number(`0.${'0'.repeat(roundDecimals)}5`);
const SCIENTIFIC_NOT_NUMBER_REGXP = /[-+]?[0-9]*.?[0-9]+([eE][-+]?[0-9]+)?/g;
const SUFFIX_REGXP = /[a-z]+$/i;
const CONVERSION_TO_REGXP = /(?<=to).*(?=hr+$)|(?<=to).*(?=hr+$)?/i;
for (const conversionFrom of (Object.keys(MemConv))) {
for (const tCase of testCases) {
const convFunc = MemConv[conversionFrom](tCase);
for (const [conversionToFn, f] of Object.entries(convFunc)) {
const conversionTo = (conversionToFn.match(CONVERSION_TO_REGXP) || [conversionToFn])[0];
const result = f();
const humanReadable = f({ hr: true });
const rounded = f({ round: roundDecimals });
const roundedAndHumanReadable = f({ hr: true, round: roundDecimals });
console.log({
value: tCase,
from: conversionFrom,
to: conversionTo,
result,
humanReadable,
rounded,
roundedAndHumanReadable,
});
}
}
}
TSVersion
test
import assert from 'assert';
function test() {
const testCases = [1, 10, 150, 1000, 74839.67346];
const HRSuffixes = Object.values(suffixes);
const roundDecimals = 2;
const precision = Number(`0.${'0'.repeat(roundDecimals)}5`);
const SCIENTIFIC_NOT_NUMBER_REGXP = /[-+]?[0-9]*.?[0-9]+([eE][-+]?[0-9]+)?/g;
const SUFFIX_REGXP = /[a-z]+$/i;
const CONVERSION_TO_REGXP = /(?<=to).*(?=hr+$)|(?<=to).*(?=hr+$)?/i;
for (const conversionFrom of (Object.keys(MemConv) as (keyof typeof MemConv)[])) {
for (const tCase of testCases) {
const convFunc = MemConv[conversionFrom](tCase);
for (const [conversionToFn, f] of Object.entries(convFunc)) {
const conversionTo = (conversionToFn.match(CONVERSION_TO_REGXP) || [conversionToFn])[0];
const expectedSuffix = suffixes[conversionTo.toLowerCase() as keyof typeof suffixes];
const multiplier = multipliers[conversionFrom][conversionToFn as keyof typeof multipliers[typeof conversionFrom]];
const expectedResult = tCase * multiplier > Number.MAX_SAFE_INTEGER
? Number.MAX_SAFE_INTEGER
: tCase * multiplier;
const result = f();
const humanReadable = f({ hr: true });
const rounded = f({ round: roundDecimals });
const roundedAndHumanReadable = f({ hr: true, round: roundDecimals });
const resHrNumber = Number((humanReadable.match(SCIENTIFIC_NOT_NUMBER_REGXP) || [''])[0]);
const resHrSuffix = (humanReadable.match(SUFFIX_REGXP) || [0])[0];
const resRoundHrNumber = Number((roundedAndHumanReadable.match(SCIENTIFIC_NOT_NUMBER_REGXP) || [''])[0]);
const resRoundHrSuffix = (roundedAndHumanReadable.match(SUFFIX_REGXP) || [0])[0];
if (/hr$/i.test(conversionToFn)) {
const resNumber = Number((humanReadable.match(SCIENTIFIC_NOT_NUMBER_REGXP) || [''])[0]);
const resSuffix = (humanReadable.match(SUFFIX_REGXP) || [0])[0];
assert(typeof result === 'string');
assert(typeof resSuffix === 'string');
assert(typeof resRoundHrNumber === 'number');
assert(typeof rounded === 'string');
assert(result === humanReadable);
assert(resSuffix === expectedSuffix);
assert(resNumber <= expectedResult + precision && resNumber >= expectedResult - precision);
} else {
assert(typeof result === 'number');
assert(result === resHrNumber);
assert(typeof rounded === 'number');
assert(result <= expectedResult + precision && result >= expectedResult - precision);
}
console.log({
value: tCase,
from: conversionFrom,
to: conversionToFn,
result,
humanReadable,
rounded,
roundedAndHumanReadable,
});
assert(typeof resHrSuffix === 'string');
assert(typeof resHrNumber === 'number');
assert(resHrSuffix === expectedSuffix);
assert(resHrSuffix === resRoundHrSuffix);
assert(HRSuffixes.includes(resHrSuffix));
}
}
}
}
test();
Usage
// GB to GB humanReadable
console.log(MemConv.GB(11.1942).toGBHr()); // 11.1942GB;
// GB to MB
console.log(MemConv.GB(11.1942).toMB());// 11194.2;
// MB to MB humanReadable
console.log(MemConv.MB(11.1942).toGB({ hr: true }));// 0.011194200000000001GB;
// MB to MB humanReadable with rounding
console.log(MemConv.MB(11.1942).toGB({ hr: true, round: 3 }));// 0.011GB;
let bytes = 1024 * 10 * 10 * 10;
console.log(getReadableFileSizeString(bytes))
will return 1000.0Кб instead of 1MB
本文标签: javascriptConverting file size in bytes to humanreadable stringStack Overflow
版权声明:本文标题:javascript - Converting file size in bytes to human-readable string - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736682941a1947515.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
1.445281982421875
which correctly rounds down to 1.4. – mpen Commented Feb 17, 2013 at 9:00YB
. Doubtful anyone will get even 1 YB for his DB. It will cost 100 trillion dollars! – Guy Commented Jan 10, 2019 at 8:49