Bayt cinsinden boyutu JavaScript'te KB, MB, GB'ye dönüştürmenin doğru yolu


258

PHP ile bayt boyutunda örtmek için bu kodu aldım .

Şimdi bu boyutları JavaScript kullanarak insan tarafından okunabilir boyutlara dönüştürmek istiyorum . Bu kodu şuna benzeyen JavaScript'e dönüştürmeye çalıştım:

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

Bunu yapmanın doğru yolu bu mu? Daha kolay bir yol var mı?


5
Bu aslında GiB, MiB ve KiB'ye dönüşür. Bu, dosya boyutları için standarttır, ancak her zaman cihaz boyutları için değildir.
David Schwartz

Yanıtlar:


761

Bundan: ( kaynak )

function bytesToSize(bytes) {
   var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
   if (bytes == 0) return '0 Byte';
   var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
   return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
}

Not: Bu orijinal kod, lütfen aşağıdaki sabit sürümü kullanın. Aliceljm artık kopyalanan kodunu aktifleştirmiyor


Şimdi, Sabit sürüm değiştirilmemiş ve ES6'ed: (topluluk tarafından)

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

    const k = 1024;
    const dm = decimals < 0 ? 0 : decimals;
    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];

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

    return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}

Şimdi, Sabit sürüm: (Stackoverflow'un topluluğu tarafından, + JSCompress tarafından küçültüldü )

function formatBytes(a,b=2){if(0===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","KB","MB","GB","TB","PB","EB","ZB","YB"][d]}

Kullanımı:

// formatBytes(bytes,decimals)

formatBytes(1024);       // 1 KB
formatBytes('1024');     // 1 KB
formatBytes(1234);       // 1.21 KB
formatBytes(1234, 3);    // 1.205 KB

Demo / kaynak:

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

    const k = 1024;
    const dm = decimals < 0 ? 0 : decimals;
    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];

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

    return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}

// ** Demo code **
var p = document.querySelector('p'),
    input = document.querySelector('input');
    
function setText(v){
    p.innerHTML = formatBytes(v);
}
// bind 'input' event
input.addEventListener('input', function(){ 
    setText( this.value )
})
// set initial text
setText(input.value);
<input type="text" value="1000">
<p></p>

PS: Değişim k = 1000veya sizes = ["..."]istediğiniz gibi ( bit veya bayt )


8
(1) neden byte = 0 "n / a"? Sadece "0 B" değil mi? (2) Math.round'un hassasiyet parametresi yoktur. (bytes / Math.pow(1024, i)).toPrecision(3)
Kullansam

4
toFixed(n)muhtemelen toPrecision(n)tüm değerler için tutarlı bir hassasiyete sahip olmaktan daha uygundur . Ve sondaki sıfırları önlemek için (ör . bytesToSize(1000) // return "1.00 KB") Kullanabiliriz parseFloat(x). Ben son çizgiyi yerine öneriyoruz: return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];. Önceki değişiklikle sonuçlar şöyledir: bytesToSize(1000) // return "1 KB"/ bytesToSize(1100) // return "1.1 KB"/ bytesToSize(1110) // return "1.11 KB/ bytesToSize(1111) // also return "1.11 KB"
MathieuLescure

3
Çoğul formun 0 için kullanıldığına inanıyorum: '0 Bayt'
nima

14
Minify'ın güzel olduğunu söyleyebilirim, ancak bir stackexchange cevabında daha ayrıntılı ve okunabilir kodlara sahip olmak daha iyidir.
donquixote

2
KB = SI birimlerinde Kelvin bayt. bu saçma. KB olmalıdır.
Brennan T

47
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
    var teraBytes = marker * marker * marker * marker; // One TB is 1024 GB

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

34
const units = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];

function niceBytes(x){

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

  while(n >= 1024 && ++l){
      n = n/1024;
  }
  //include a decimal point and a tenths-place digit if presenting 
  //less than ten of KB or greater units
  return(n.toFixed(n < 10 && l > 0 ? 1 : 0) + ' ' + units[l]);
}

Sonuçlar:

niceBytes(435)                 // 435 bytes
niceBytes(3398)                // 3.3 KB
niceBytes(490398)              // 479 KB
niceBytes(6544528)             // 6.2 MB
niceBytes(23483023)            // 22 MB
niceBytes(3984578493)          // 3.7 GB
niceBytes(30498505889)         // 28 GB
niceBytes(9485039485039445)    // 8.4 PB

15

Filesizejs kütüphanesini kullanabilirsiniz .


Sanırım bu kütüphane doğru temsili verir, çünkü 1024 bayt 1000 KB değil 1 KB'dir (diğer bazı çözümlerin sağladığı gibi). Thanks @maurocchi
WM

3
@WM bu ifade doğru değil. 1 KB = 1000 bayt. Bir Kibibyte'de 1024 bayt var. Geçmişte karışıklık vardı, bu nedenle bu iki terim boyut farkını tam olarak açıklıyor.
Brennan T

2
@BrennanT Yaşınıza bağlıdır. 1KB eskiden 1024 bayttı ve belirli bir yaşın üzerindeki çoğu insan hala böyle görüyor.
kojow7

14

Baytlarla ilgili boyutları temsil etmenin 2 gerçek yolu vardır, bunlar SI birimleri (10 ^ 3) veya IEC birimleri (2 ^ 10) 'dır. JEDEC de var ama yöntemleri belirsiz ve kafa karıştırıcı. Diğer örneklerin kilobaytı temsil etmek için KB yerine KB kullanmak gibi hatalar olduğunu fark ettim, bu yüzden şu anda kabul edilen ölçü birimlerini kullanarak bu vakaların her birini çözecek bir işlev yazmaya karar verdim.

Sonunda sayının biraz daha iyi görünmesini sağlayacak bir biçimlendirme biti var (en azından gözüme), amacınıza uymuyorsa bu biçimlendirmeyi kaldırmaktan çekinmeyin.

Zevk almak.

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

13

İşte bir astar:

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

Ya da:

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


Güzel!, Ama 1k 1024 1000 değilse?
l2aelba

2
Bu hesaplama, bir çok 2 ^ 20 gibi 1k 10 ^ 2 olarak, 1m muamele edilmesini içerir. 1k değerinin 1000 olmasını istiyorsanız log10'u kullanmak için biraz değiştirebilirsiniz.
iDaN5x

1
İşte val => 'BKMGT'[~~(Math.log10(val)/3)]
1K'yı

1
Bu güzel! Ben fonksiyonumdan istediğim tam dize dönmek için bu genişletti:i = ~~(Math.log2(b)/10); return (b/Math.pow(1024,i)).toFixed(2) + ("KMGTPEZY"[i-1]||"") + "B"
v0rtex

4

Bitsel işlem kullanmak daha iyi bir çözüm olacaktır. Bunu dene

function formatSizeUnits(bytes)
{
    if ( ( bytes >> 30 ) & 0x3FF )
        bytes = ( bytes >>> 30 ) + '.' + ( bytes & (3*0x3FF )) + 'GB' ;
    else if ( ( bytes >> 20 ) & 0x3FF )
        bytes = ( bytes >>> 20 ) + '.' + ( bytes & (2*0x3FF ) ) + 'MB' ;
    else if ( ( bytes >> 10 ) & 0x3FF )
        bytes = ( bytes >>> 10 ) + '.' + ( bytes & (0x3FF ) ) + 'KB' ;
    else if ( ( bytes >> 1 ) & 0x3FF )
        bytes = ( bytes >>> 1 ) + 'Bytes' ;
    else
        bytes = bytes + 'Byte' ;
    return bytes ;
}

1
Kalan baytları edinin. Bu ondalık bölümü sağlayacaktır.
Buzz Lightyear

1
Onun 1024. 100 gerekiyorsa bitleri uygun şekilde kaydırın.
Buzz Lightyear


3
Lütfen kodu anlamadan veya en azından test etmeden internetten almayın. Bu sadece yanlış olan kodun iyi bir örneğidir. 3 ("1Bytes" döndürür) veya 400000'i geçerek çalıştırmayı deneyin.
Amir Haghighat

10
Sevgili Amir Haghighat, bu sadece benim tarafımdan yazılmış temel bir kod. Javasript post 32 bit tam sayı değeri, tamsayı sadece dört bayt olduğundan kod çalışmaz. Bunlar bilmeniz gereken temel programlama bilgileridir. Stackoverflow kaşık beslemek için değil, sadece insanları yönlendirmek içindir.
Buzz Lightyear6

4

Aliceljm'in cevabına göre, ondalıktan sonra 0'ı kaldırdım:

function formatBytes(bytes, decimals) {
    if(bytes== 0)
    {
        return "0 Byte";
    }
    var k = 1024; //Or 1 kilo = 1000
    var sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB"];
    var i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(decimals)) + " " + sizes[i];
}

2

Başlangıçta üzerinde çalıştığım bir dosya yükleme projesi için @Aliceljm'in cevabını kullandım , ancak son zamanlarda bir dosyanın olduğu 0.98kbgibi okunduğu bir sorunla karşılaştım 1.02mb. İşte şimdi kullandığım kod.

function formatBytes(bytes){
  var kb = 1024;
  var ndx = Math.floor( Math.log(bytes) / Math.log(kb) );
  var fileSizeTypes = ["bytes", "kb", "mb", "gb", "tb", "pb", "eb", "zb", "yb"];

  return {
    size: +(bytes / kb / kb).toFixed(2),
    type: fileSizeTypes[ndx]
  };
}

Yukarıdaki gibi bir dosya eklendikten sonra çağrılabilir

// In this case `file.size` equals `26060275` 
formatBytes(file.size);
// returns `{ size: 24.85, type: "mb" }`

Verilmiş, Windows dosyayı olduğu gibi okuyor 24.8mbama ekstra hassasiyetle iyiyim.


2

Bu çözüm önceki çözümlere dayanır, ancak hem metrik hem de ikili birimleri dikkate alır:

function formatBytes(bytes, decimals, binaryUnits) {
    if(bytes == 0) {
        return '0 Bytes';
    }
    var unitMultiple = (binaryUnits) ? 1024 : 1000; 
    var unitNames = (unitMultiple === 1024) ? // 1000 bytes in 1 Kilobyte (KB) or 1024 bytes for the binary version (KiB)
        ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']: 
        ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
    var unitChanges = Math.floor(Math.log(bytes) / Math.log(unitMultiple));
    return parseFloat((bytes / Math.pow(unitMultiple, unitChanges)).toFixed(decimals || 0)) + ' ' + unitNames[unitChanges];
}

Örnekler:

formatBytes(293489203947847, 1);    // 293.5 TB
formatBytes(1234, 0);   // 1 KB
formatBytes(4534634523453678343456, 2); // 4.53 ZB
formatBytes(4534634523453678343456, 2, true));  // 3.84 ZiB
formatBytes(4566744, 1);    // 4.6 MB
formatBytes(534, 0);    // 534 Bytes
formatBytes(273403407, 0);  // 273 MB

2

function bytesToSize(bytes) {
  var sizes = ['B', 'K', 'M', 'G', 'T', 'P'];
  for (var i = 0; i < sizes.length; i++) {
    if (bytes <= 1024) {
      return bytes + ' ' + sizes[i];
    } else {
      bytes = parseFloat(bytes / 1024).toFixed(2)
    }
  }
  return bytes + ' P';
}

console.log(bytesToSize(234));
console.log(bytesToSize(2043));
console.log(bytesToSize(20433242));
console.log(bytesToSize(2043324243));
console.log(bytesToSize(2043324268233));
console.log(bytesToSize(2043324268233343));


2

var SIZES = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];

function formatBytes(bytes, decimals) {
  for(var i = 0, r = bytes, b = 1024; r > b; i++) r /= b;
  return `${parseFloat(r.toFixed(decimals))} ${SIZES[i]}`;
}


1

@Aliceljm yanıtını burada güncelliyorum. Ondalık basamak 1,2 basamaklı sayılar için önemli olduğundan, ilk ondalık basamak yuvarlanır ve ilk ondalık basamak korunur. 3 basamaklı sayı için, birimlerin yerini yuvarlayıp tüm ondalık basamakları yok sayıyorum.

getMultiplers : function(bytes){
    var unit = 1000 ;
    if (bytes < unit) return bytes ;
    var exp = Math.floor(Math.log(bytes) / Math.log(unit));
    var pre = "kMGTPE".charAt(exp-1);
    var result = bytes / Math.pow(unit, exp);
    if(result/100 < 1)
        return (Math.round( result * 10 ) / 10) +pre;
    else
        return Math.round(result) + pre;
}

0

Bir bayt insana şu şekilde gösterilmelidir:

function bytesToHuman(bytes, decimals = 2) {
  // https://en.wikipedia.org/wiki/Orders_of_magnitude_(data)
  const units = ["bytes", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"]; // etc

  let i = 0;
  let h = 0;

  let c = 1 / 1023; // change it to 1024 and see the diff

  for (; h < c && i < units.length; i++) {
    if ((h = Math.pow(1024, i) / bytes) >= c) {
      break;
    }
  }

  // remove toFixed and let `locale` controls formatting
  return (1 / h).toFixed(decimals).toLocaleString() + " " + units[i];
}

// test
for (let i = 0; i < 9; i++) {
  let val = i * Math.pow(10, i);
  console.log(val.toLocaleString() + " bytes is the same as " + bytesToHuman(val));

}

// let's fool around
console.log(bytesToHuman(1023));
console.log(bytesToHuman(1024));
console.log(bytesToHuman(1025));

0

Sadece girdilerimi paylaşmak istedim. Bu problemim vardı, bu yüzden benim çözümüm bu. Bu, alt birimleri daha yüksek birimlere dönüştürür ve bunun tersi de yalnızca argümanı sağlar toUnitvefromUnit

export function fileSizeConverter(size: number, fromUnit: string, toUnit: string ): number | string {
  const units: string[] = ['B', 'KB', 'MB', 'GB', 'TB'];
  const from = units.indexOf(fromUnit.toUpperCase());
  const to = units.indexOf(toUnit.toUpperCase());
  const BASE_SIZE = 1024;
  let result: number | string = 0;

  if (from < 0 || to < 0 ) { return result = 'Error: Incorrect units'; }

  result = from < to ? size / (BASE_SIZE ** to) : size * (BASE_SIZE ** from);

  return result.toFixed(2);
}

Fikri buradan aldım


0
function bytes2Size(byteVal){
    var units=["Bytes", "KB", "MB", "GB", "TB"];
    var kounter=0;
    var kb= 1024;
    var div=byteVal/1;
    while(div>=kb){
        kounter++;
        div= div/kb;
    }
    return div.toFixed(1) + " " + units[kounter];
}

Bu fonksiyonun anlaşılması ve takip edilmesi kolaydır - herhangi bir dilde uygulayabilirsiniz.
1kb'den

Sadece hızlı bir not, İkili önekler arasında farklılıklar vardır. Daha okuyabilir Bazı takip SI temel 10 kural ve bazı takip tabanı 2. burada . Eğer k yerine dividsion arasında 1024 olarak kabul Ancak, sadece kullanabilirsiniz vardiya operatörü gibi byteVal >> 10. Ayrıca , 1 ile bölünme yerine tamsayılara gerçek sayılar atmak için daha iyi kullanabilirsinizMath.trunc() .
Kurnaz

Lütfen sadece kodu yanıt olarak göndermeyin, aynı zamanda kodunuzun ne yaptığını ve sorunun sorununu nasıl çözdüğünü de açıklayın. Açıklamalı cevaplar genellikle daha yüksek kalitededir ve yukarı oy alma olasılığı daha yüksektir.
Mark Rotteveel

-7

Bu basit çözümü deneyin.

var files = $("#file").get(0).files;               
                var size = files[0].size;
                if (size >= 5000000) {
alert("File size is greater than or equal to 5 MB");
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.