Korrekt måte å konvertere størrelse i bytes til KB, MB, GB i JavaScript


Jeg fikk denne koden for å konvertere størrelse i bytes via PHP.

Nå vil jeg konvertere disse størrelsene til menneskelig lesbare størrelser ved hjelp av JavaScript. Jeg prøvde å konvertere denne koden til JavaScript, som ser slik ut:

function formatSizeUnits(bytes){
  if      (bytes >= 1073741824) { bytes = (bytes / 1073741824).toFixed(2) + " GB"; }
  else if (bytes >= 1048576)    { bytes = (bytes / 1048576).toFixed(2) + " MB"; }
  else if (bytes >= 1024)       { bytes = (bytes / 1024).toFixed(2) + " KB"; }
  else if (bytes > 1)           { bytes = bytes + " bytes"; }
  else if (bytes == 1)          { bytes = bytes + " byte"; }
  else                          { bytes = "0 bytes"; }
  return bytes;
}

Er dette den riktige måten å gjøre dette på? Finnes det en enklere måte?

Svar #1

Fra dette: (kilde)


Uminifisert og ES6'et: (av fellesskapet)

function formatBytes(bytes, decimals = 2) {
    if (!+bytes) return '0 Bytes'

    const k = 1024
    const dm = decimals < 0 ? 0 : decimals
    const sizes = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']

    const i = Math.floor(Math.log(bytes) / Math.log(k))

    return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`
}

// Demo code
document.body.innerHTML += `<input type="text" oninput="document.querySelector('p').innerHTML=formatBytes(this.value)" value="1000"><p>1000 Bytes</p>`

Minifisert versjon (av StackOverflows fellesskap, minifisert av JSCompress)

function formatBytes(a,b=2){if(!+a)return"0 Bytes";const c=0>b?0:b,d=Math.floor(Math.log(a)/Math.log(1024));return`${parseFloat((a/Math.pow(1024,d)).toFixed(c))} ${["Bytes","KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"][d]}`}

Bruk:

// formatBytes(bytes, decimals)

formatBytes(1024)       // 1 KiB
formatBytes('1024')     // 1 KiB
formatBytes(1234)       // 1.21 KiB
formatBytes(1234, 3)    // 1.205 KiB
formatBytes(0)          // 0 Bytes
formatBytes('0')        // 0 Bytes

PS: Endre k=1000 eller sizes=["..."] som du vil (biter eller bytes)

Svar #2

Denne løsningen inkluderer et desimaltegn og et tidels-siffer hvis den presenterer mindre enn ti KB eller større enheter

const units = ['bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
   
function niceBytes(x){

  let l = 0, n = parseInt(x, 10) || 0;

  while(n >= 1024 && ++l){
      n = n/1024;
  }
  
  return(n.toFixed(n < 10 && l > 0 ? 1 : 0) + ' ' + units[l]);
}

Resultater :

niceBytes(7)                   // 7 bytes
niceBytes(435)                 // 435 bytes
niceBytes(3398)                // 3.3 KiB
niceBytes(490398)              // 479 KiB
niceBytes(6544528)             // 6.2 MiB
niceBytes(23483023)            // 22 MiB
niceBytes(3984578493)          // 3.7 GiB
niceBytes(30498505889)         // 28 GiB
niceBytes(9485039485039445)    // 8.4 PiB

Merk: Bruk forkortelsene "Kib" osv. når du bruker base 1024, fordi "KB" osv. faktisk refererer til base 1000. Hvis du ønsker å beregne verdien til base 1000, erstatt bare 1024 med 1000 i denne funksjonen, og bruk de riktige enhetene (kB, MB, osv.)

Svar #3

function formatBytes(bytes) {
    var marker = 1024; // Change to 1000 if required
    var decimal = 3; // Change as required
    var kiloBytes = marker; // One Kilobyte is 1024 bytes
    var megaBytes = marker * marker; // One MB is 1024 KB
    var gigaBytes = marker * marker * marker; // One GB is 1024 MB
  
    // return bytes if less than a KB
    if(bytes < kiloBytes) return bytes + " Bytes";
    // return KB if less than a MB
    else if(bytes < megaBytes) return(bytes / kiloBytes).toFixed(decimal) + " KB";
    // return MB if less than a GB
    else if(bytes < gigaBytes) return(bytes / megaBytes).toFixed(decimal) + " MB";
    // return GB if less than a TB
    else return(bytes / gigaBytes).toFixed(decimal) + " GB";
}

Svar #4

Her er en en-liner:

val => ['Bytes','Kb','Mb','Gb','Tb'][Math.floor(Math.log2(val)/10)]

Eller til og med:

v => 'BKMGT'[~~(Math.log2(v)/10)]

Med telling:

function shortenBytes(n) {
    const k = n > 0 ? Math.floor((Math.log2(n)/10)) : 0;
    const rank = (k > 0 ? 'KMGT'[k - 1] : '') + 'b';
    const count = Math.floor(n / Math.pow(1024, k));
    return count + rank;
}

Svar #5

Det finnes 2 ekte måter å representere størrelser relatert til byte på, de er SI-enheter (10^3) eller IEC-enheter (2^10). Det finnes også JEDEC, men deres metode er tvetydig og forvirrende. Jeg la merke til at de andre eksemplene har feil, for eksempel å bruke KB i stedet for kB for å representere en kilobyte, så jeg bestemte meg for å skrive en funksjon som vil løse hver av disse tilfellene ved å bruke området av nåværende godkjente måleenheter.

Det er et formateringsbit på slutten som vil få tallet til å se litt bedre ut (i det minste for mitt øye), føl deg fri til å fjerne den formateringen hvis det ikke passer ditt formål.

Kos deg.

// pBytes: the size in bytes to be converted.
// pUnits: 'si'|'iec' si units means the order of magnitude is 10^3, iec uses 2^10

function prettyNumber(pBytes, pUnits) {
    // Handle some special cases
    if(pBytes == 0) return '0 Bytes';
    if(pBytes == 1) return '1 Byte';
    if(pBytes == -1) return '-1 Byte';

    var bytes = Math.abs(pBytes)
    if(pUnits && pUnits.toLowerCase() && pUnits.toLowerCase() == 'si') {
        // SI units use the Metric representation based on 10^3 as a order of magnitude
        var orderOfMagnitude = Math.pow(10, 3);
        var abbreviations = ['Bytes', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
    } else {
        // IEC units use 2^10 as an order of magnitude
        var orderOfMagnitude = Math.pow(2, 10);
        var abbreviations = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
    }
    var i = Math.floor(Math.log(bytes) / Math.log(orderOfMagnitude));
    var result = (bytes / Math.pow(orderOfMagnitude, i));

    // This will get the sign right
    if(pBytes < 0) {
        result *= -1;
    }

    // This bit here is purely for show. it drops the percision on numbers greater than 100 before the units.
    // it also always shows the full number of bytes if bytes is the unit.
    if(result >= 99.995 || i==0) {
        return result.toFixed(0) + ' ' + abbreviations[i];
    } else {
        return result.toFixed(2) + ' ' + abbreviations[i];
    }
}

Svar #6

Du kan bruke filesizejs-biblioteket.

Relaterte artikler