// from http://scratch99.com/web-development/javascript/convert-bytes-to-mb-kb/ | |
function bytesToSize(bytes) { | |
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; | |
if (bytes == 0) return 'n/a'; | |
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024))); | |
if (i == 0) return bytes + ' ' + sizes[i]; | |
return (bytes / Math.pow(1024, i)).toFixed(1) + ' ' + sizes[i]; | |
}; |
ES6 and airbnb's eslint compliant version:
function bytesToSize(bytes) {
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']
if (bytes === 0) return 'n/a'
const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)), 10)
if (i === 0) return `${bytes} ${sizes[i]})`
return `${(bytes / (1024 ** i)).toFixed(1)} ${sizes[i]}`
}
function bytesToSize(bytes) {
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']
if (bytes === 0) return 'n/a'
const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)), 10)
if (i === 0) return ${bytes} ${sizes[i]})
return ${(bytes / (1024 ** i)).toFixed(1)} ${sizes[i]}
}
With little typo fixed on line 5:
function bytesToSize(bytes) {
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']
if (bytes === 0) return 'n/a'
const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)), 10)
if (i === 0) return `${bytes} ${sizes[i]}`
return `${(bytes / (1024 ** i)).toFixed(1)} ${sizes[i]}`
}
Some may doesn't like having a seperator so:
function bytesToSize(bytes, seperator = "") {
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']
if (bytes == 0) return 'n/a'
const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)), 10)
if (i === 0) return `${bytes}${seperator}${sizes[i]}`
return `${(bytes / (1024 ** i)).toFixed(1)}${seperator}${sizes[i]}`
}
console.log( bytesToSize(2659633) ); // 2.5MB
console.log( bytesToSize(2659633, " ") ); // 2.5 MB
console.log( bytesToSize(2659633, "-") ); // 2.5-MB
I had a need to format negative values, but Math.log(x)
returns NaN
if x
is negative, so I pass bytes
through Math.abs()
first.
function bytesToSize(bytes) {
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
if (bytes === 0) return 'n/a';
const i = parseInt(Math.floor(Math.log(Math.abs(bytes)) / Math.log(1024)), 10);
if (i === 0) return `${bytes} ${sizes[i]}`;
return `${(bytes / (1024 ** i)).toFixed(1)} ${sizes[i]}`;
}
console.log(bytesToSize(1234567)); // 1.2 MB
console.log(bytesToSize(-1234567)); // -1.2 MB
@jedfoster I used your code, but just pointing out something... If you're only rendering "Bytes", there's a dangling closing parenthesis.
e.g. "Bytes)"
- 1 redundant line removed
- added suffix param
- fixed error if size more then 1023 TB
function prettySize(bytes, separator = '', postFix = '') {
if (bytes) {
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
const i = Math.min(parseInt(Math.floor(Math.log(bytes) / Math.log(1024)), 10), sizes.length - 1);
return `${(bytes / (1024 ** i)).toFixed(i ? 1 : 0)}${separator}${sizes[i]}${postFix}`;
}
return 'n/a';
}
thank you
fixed a type error on line 4, Argument of type 'number' is not assignable to parameter of type 'string'
prettySize(bytes, separator = '', postFix = '') {
if (bytes) {
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
const i = Math.min(parseInt(Math.floor(Math.log(bytes) / Math.log(1024)).toString(), 10), sizes.length - 1);
return `${(bytes / (1024 ** i)).toFixed(i ? 1 : 0)}${separator}${sizes[i]}${postFix}`;
}
return 'n/a';
}
A little bit of code for people who want the reverse.
Basically adapted this from https://stackoverflow.com/a/31625253/104461
function printpower (n, base, power) {
if (base === 2) { // 1 << power is approx 10x faster than Math.pow(2, power)
console.log(n * (1 << power))
} else {
console.log(n * Math.pow(base, power))
}
}
const humanReadable = '86 MB'
const [n, abbreviation] = humanReadable.split(/\s+/)
if (abbreviation) {
if (/K(iB)?$/.test(abbreviation)) {
printpower(n, 2, 10)
} else if (/M(iB)?$/.test(abbreviation)) {
printpower(n, 2, 20)
} else if (/G(iB)?$/.test(abbreviation)) {
printpower(n, 2, 30)
} else if (/T(iB)?$/.test(abbreviation)) {
printpower(n, 2, 40)
} else if (/KB$/.test(abbreviation)) {
printpower(n, 10, 3)
} else if (/MB$/.test(abbreviation)) {
printpower(n, 10, 6)
} else if (/GB$/.test(abbreviation)) {
printpower(n, 10, 9)
} else if (/TB$/.test(abbreviation)) {
printpower(n, 10, 12)
}
} else {
console.log(n)
}
Edit: the if
statement is probably pretty expensive, and so are the Regular Expressions (at a minimum, should be compiled once as const
variables), so there is room for incremental optimization!
Thanks all of you
TypeScript version:
export function bytesToSize(bytes: number): string {
const sizes: string[] = ['Bytes', 'KB', 'MB', 'GB', 'TB']
if (bytes === 0) return 'n/a'
const i: number = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)).toString())
if (i === 0) return `${bytes} ${sizes[i]}`
return `${(bytes / Math.pow(1024, i)).toFixed(1)} ${sizes[i]}`
}
Strength and power of open source community. I'm shocked and impressed. Thanks to all, guys.
function bytesToSize(bytes) {
const units = ["byte", "kilobyte", "megabyte", "terabyte", "petabyte"];
const unit = Math.floor(Math.log(bytes) / Math.log(1024));
return new Intl.NumberFormat("en", {style: "unit", unit: units[unit]}).format(bytes / 1024 ** unit);
}
To expand on the typescript version, I don't think the parseInt(...)
is required. Also, in the unlikely case that you exceed 999.9 TB
, you end up in xxx.x undefined
territory.
Here is a fixed Typescript version:
export function bytesToSize(bytes: number): string {
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
if (bytes === 0) return 'n/a';
const i = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), sizes.length - 1);
if (i === 0) return `${bytes} ${sizes[i]}`;
return `${(bytes / (1024 ** i)).toFixed(1)} ${sizes[i]}`;
}
With Jest spec:
describe('bytesToSize', () => {
test.each([
[0, 'n/a'],
[1, '1 Bytes'],
[2000, '2.0 KB'],
[30000, '29.3 KB'],
[400000, '390.6 KB'],
[5000000, '4.8 MB'],
[60000000, '57.2 MB'],
[700000000, '667.6 MB'],
[8000000000, '7.5 GB'],
[90000000000, '83.8 GB'],
[100000000000, '93.1 GB'],
[1100000000000, '1.0 TB'],
[12000000000000, '10.9 TB'],
[130000000000000, '118.2 TB'],
[1400000000000000, '1273.3 TB'],
[15000000000000000, '13642.4 TB'],
])('.bytesToSize(%p)', (
val: number,
expected: string,
) => {
expect(
bytesToSize(val),
).toBe(expected);
});
});
Using the Intl.NumberFormat
for local friendly conversions
export function bytesToSize(bytes: number): string {
const units = ['byte', 'kilobyte', 'megabyte', 'gigabyte', 'terabyte'];
const navigatorLocal = navigator.languages && navigator.languages.length >= 0 ? navigator.languages[0] : 'en-US'
const unitIndex = Math.max(0, Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), units.length - 1));
return Intl.NumberFormat(navigatorLocal, {
style: 'unit',
unit : units[unitIndex]
}).format(bytes / (1024 ** unitIndex))
}
Nice