Сколько байтов в строке JavaScript?

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

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

Ответ 1

Значения

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

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

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

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

Ответ 2

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

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

Источник

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

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

Источник

Ответ 3

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

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

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

Ответ 4

Вы можете использовать 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 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)
);

Ответ 5

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

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

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

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

Ответ 6

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

var str = "\u2620"; // => "☠"
str.length; // => 1 (character)
Buffer.from(str).length // => 3 (bytes)

Ответ 7

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

Ответ 8

Ответ от 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;
}

например.

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)

Ответ 9

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

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

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

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

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

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

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

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

Ответ 10

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

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

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

Результат: символы не сохраняются динамически. И не только с 16 бит. - Хорошо, возможно, только для моего случая (Embedded 128 MB RAM Device, V8 Engine С++/QT). Кодировка символов не имеет никакого отношения к размеру в ядре механизма javascript. Например. encodingURI и т.д. полезен только для передачи и хранения данных на высоком уровне.

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

Ответ 11

Один элемент в строке JavaScript рассматривается как единый модуль кода UTF-16. То есть символы Strings сохраняются в 16-битном (1 единица кода), а 16-бит равен 2 байтам (8 бит = 1 байт).

Метод charCodeAt() может использоваться для возврата целого числа от 0 до 65535, представляющего кодовый блок UTF-16 по данному индексу.

codePointAt() может использоваться для возврата всего значения кодовой точки для символов Юникода, например. UTF-32.

Когда символ UTF-16 не может быть представлен в одном 16-битном блоке кода, он будет иметь суррогатную пару и, следовательно, использовать два кодовых блока (2 x 16 бит = 4 байта)

Смотрите кодировки Unicode для разных кодировок и диапазонов их кода.

Ответ 12

Вы можете попробовать следующее:

  var b = str.match(/[^\x00-\xff]/g);
  return (str.length + (!b ? 0: b.length)); 

Это сработало для меня.

Ответ 13

Это 3 способа, которыми я пользуюсь:

  1. TextEncoder()

    (new TextEncoder().encode("myString")).length)

  2. Blob

    new Blob(["myString"]).size)

  3. Буфер

    Buffer.byteLength("myString", 'utf8'))