Сколько байтов в строке 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 способа, которыми я пользуюсь:
TextEncoder()
(new TextEncoder().encode("myString")).length)
Blob
new Blob(["myString"]).size)
Буфер
Buffer.byteLength("myString", 'utf8'))