Сколько байт в строке JavaScript? - PullRequest
71 голосов
/ 08 февраля 2010

У меня есть строка JavaScript, которая составляет около 500 КБ при отправке с сервера в UTF-8. Как узнать его размер в JavaScript?

Я знаю, что JavaScript использует UCS-2, так что это означает 2 байта на символ. Однако зависит ли это от реализации JavaScript? Или на странице кодировки или, может быть, типа контента?

Ответы [ 12 ]

58 голосов
/ 31 августа 2012

Эта функция возвращает размер байта любой строки UTF-8, которую вы ей передаете.

function byteCount(s) {
    return encodeURI(s).split(/%..|./).length - 1;
}

Источник

Движки JavaScript могут свободно использовать UCS-2 или UTF-16 для внутренних целей. Большинство известных мне движков используют UTF-16, но какой бы выбор они ни сделали, это всего лишь деталь реализации, которая не повлияет на характеристики языка.

Однако сам язык ECMAScript / JavaScript предоставляет символы в соответствии с UCS-2, а не UTF-16.

Источник

38 голосов
/ 09 декабря 2014

Если вы используете node.js, есть более простое решение, использующее buffers :

function getBinarySize(string) {
    return Buffer.byteLength(string, 'utf8');
}

Для этого есть библиотека npm: https://www.npmjs.org/package/utf8-binary-cutter (с уважением)

26 голосов
/ 08 февраля 2010

String значения не зависят от реализации, в соответствии со спецификацией ECMA-262 3-го издания , каждый символ представляет одну 16-битную единицу текста UTF-16 :

4.3.16 Строковое значение

Строковое значение является членом типа String и является конечная упорядоченная последовательность нуля или больше 16-битных целых чисел без знака.

ПРИМЕЧАНИЕ Хотя каждое значение обычно представляет собой одну 16-битную единицу UTF-16 текст, язык не разместить какие-либо ограничения или требования на значения, за исключением того, что они будут 16-разрядные целые числа без знака.

17 голосов
/ 18 мая 2010

Попробуйте эту комбинацию с помощью функции unescape js:

var byteAmount = unescape(encodeURIComponent(yourString)).length

Пример процесса полного кодирования:


    var s  = "1 a ф № @ ®"; //length is 11
    var s2 = encodeURIComponent(s); //length is 41
    var s3 = unescape(s2); //length is 15 [1-1,a-1,ф-2,№-3,@-1,®-2]
    var s4 = escape(s3); //length is 39
    var s5 = decodeURIComponent(s4); //length is 11

См. Дополнительный экран http://dl.dropbox.com/u/2086213/%3Dcoding%3D/js_utf_byte_length.png (Я новый пользователь, поэтому я не могу использовать тег img)

12 голосов
/ 10 сентября 2018

Вы можете использовать Blob , чтобы получить размер строки в байтах.

Примеры:

console.info(
  new Blob(['?']).size,                             // 4
  new Blob(['?']).size,                             // 4
  new Blob(['??']).size,                           // 8
  new Blob(['??']).size,                           // 8
  new Blob(['I\'m a string']).size,                  // 12

  // from Premasagar correction of Lauri's answer for
  // strings containing lone characters in the surrogate pair range:
  // https://stackoverflow.com/a/39488643/6225838
  new Blob([String.fromCharCode(55555)]).size,       // 3
  new Blob([String.fromCharCode(55555, 57000)]).size // 4 (not 6)
);
7 голосов
/ 17 февраля 2017

Обратите внимание, что если вы нацелены на node.js, вы можете использовать Buffer.from(string).length:

var str = "\u2620"; // => "☠"
str.length; // => 1 (character)
Buffer.from(str).length // => 3 (bytes)
6 голосов
/ 30 апреля 2015

UTF-8 кодирует символы, используя от 1 до 4 байтов на кодовую точку.Как указала CMS в принятом ответе, JavaScript будет хранить каждый символ внутренне, используя 16 бит (2 байта).

Если вы анализируете каждый символ в строке с помощью цикла и подсчитывает количество байтов, используемых на кодовую точку, а затем умножьте общее количество на 2, вы должны использовать JavaScript в байтах для этой строки в кодировке UTF-8.Возможно, что-то вроде этого:

      getStringMemorySize = function( _string ) {
        "use strict";

        var codePoint
            , accum = 0
        ;

        for( var stringIndex = 0, endOfString = _string.length; stringIndex < endOfString; stringIndex++ ) {
            codePoint = _string.charCodeAt( stringIndex );

            if( codePoint < 0x100 ) {
                accum += 1;
                continue;
            }

            if( codePoint < 0x10000 ) {
                accum += 2;
                continue;
            }

            if( codePoint < 0x1000000 ) {
                accum += 3;
            } else {
                accum += 4;
            }
        }

        return accum * 2;
    }

Примеры:

getStringMemorySize( 'I'    );     //  2
getStringMemorySize( '❤'    );     //  4
getStringMemorySize( '?'   );     //  8
getStringMemorySize( 'I❤?' );     // 14
4 голосов
/ 13 октября 2017

Размер строки JavaScript составляет

  • Pre-ES6 : 2 байта на символ
  • ES6 и выше: 2 байта на символ, или 5 или более байтов на символ

Pre-ES6
Всегда 2 байта на символ. UTF-16 не допускается, потому что спецификация говорит, что «значения должны быть 16-разрядными целыми числами без знака». Так как строки UTF-16 могут использовать 3 или 4 байтовые символы, это нарушит требование 2 байта. Важно отметить, что, хотя UTF-16 не может поддерживаться полностью, стандарт требует, чтобы два используемых байтовых символа были действительными символами UTF-16. Другими словами, строки JavaScript до ES6 поддерживают подмножество символов UTF-16.

ES6 и позже
2 байта на символ или 5 или более байтов на символ. Дополнительные размеры вступают в игру, потому что ES6 (ECMAScript 6) добавляет поддержку для кодировки Unicode, выходящей за пределы . Использование экранирования Юникода выглядит следующим образом: \ u {1D306}

Практические заметки

  • Это не относится к внутренней реализации конкретного движка. За Например, некоторые движки используют структуры данных и библиотеки с полным Поддержка UTF-16, но то, что они предоставляют внешне, не должно быть полная поддержка UTF-16. Также двигатель может обеспечить внешний UTF-16 поддержка, но не обязана это делать.

  • Для ES6 практически говорящих персонажей никогда не будет больше 5 длина байта (2 байта для точки выхода + 3 байта для Unicode код), потому что последняя версия Unicode имеет только 136,755 возможные символы, которые легко вписываются в 3 байта. Однако это технически не ограничен стандартом, так что в принципе один символ может использовать, скажем, 4 байта для кодовой точки и 6 байтов общий.

  • Большинство приведенных здесь примеров кода для расчета размера байта, похоже, не учитывают экранирование кодовой точки ES6 Unicode, поэтому в некоторых случаях результаты могут быть неверными.

2 голосов
/ 14 сентября 2016

Ответ от Lauri Oherd хорошо работает для большинства строк, встречающихся в дикой природе, но потерпит неудачу, если строка содержит одиночные символы в диапазоне суррогатных пар от 0xD800 до 0xDFFF. Э.Г.

byteCount(String.fromCharCode(55555))
// URIError: URI malformed

Эта более длинная функция должна обрабатывать все строки:

function bytes (str) {
  var bytes=0, len=str.length, codePoint, next, i;

  for (i=0; i < len; i++) {
    codePoint = str.charCodeAt(i);

    // Lone surrogates cannot be passed to encodeURI
    if (codePoint >= 0xD800 && codePoint < 0xE000) {
      if (codePoint < 0xDC00 && i + 1 < len) {
        next = str.charCodeAt(i + 1);

        if (next >= 0xDC00 && next < 0xE000) {
          bytes += 4;
          i++;
          continue;
        }
      }
    }

    bytes += (codePoint < 0x80 ? 1 : (codePoint < 0x800 ? 2 : 3));
  }

  return bytes;
}

1007 * Е.Г. *

bytes(String.fromCharCode(55555))
// 3

Он правильно рассчитает размер для строк, содержащих суррогатные пары:

bytes(String.fromCharCode(55555, 57000))
// 4 (not 6)

Результаты можно сравнить со встроенной функцией Node Buffer.byteLength:

Buffer.byteLength(String.fromCharCode(55555), 'utf8')
// 3

Buffer.byteLength(String.fromCharCode(55555, 57000), 'utf8')
// 4 (not 6)
1 голос
/ 06 декабря 2016

Я работаю со встроенной версией V8 Engine. Я проверил одну строку. Нажимая каждый шаг 1000 символов. UTF-8.

Первый тест с однобайтовым (8 бит, ANSI) символом «A» (шестнадцатеричное: 41). Второй тест с двухбайтовым символом (16 бит) «Ω» (шестнадцатеричный: CE A9) и третий тест с трехбайтовым символом (24 бита) «☺» (шестнадцатеричный: E2 98 BA).

Во всех трех случаях устройство печатает из памяти на 888 000 знаков и использование ок. 26 348 кб в оперативной памяти.

Результат: символы не сохраняются динамически. И не только с 16 бит. - Ладно, возможно, только для моего случая (встроенное ОЗУ 128 МБ, V8 Engine C ++ / QT) - Кодировка символов не имеет никакого отношения к размеру в ram движка javascript. Например. encodingURI и т. д. полезны только для передачи и хранения данных высокого уровня.

Внедрено или нет, факт в том, что символы хранятся не только в 16 битах. К сожалению, у меня нет 100% ответа, что делают Javascript на низком уровне. Btw. Я тестировал то же самое (первый тест выше) с массивом символов «А». Толкает 1000 пунктов каждый шаг. (Точно такой же тест. Просто заменил строку на массив) И система вывела из памяти (разыскивается) после использования 10 416 КБ и длины массива 1 337 000. Таким образом, движок javascript не просто ограничен. Это немного сложнее.

...