Tengo una cadena de JavaScript que es de aproximadamente 500K cuando se envía desde el servidor en UTF-8. ¿Cómo puedo saber su tamaño en JavaScript?
Sé que JavaScript usa UCS-2, entonces eso significa 2 bytes por carácter. Sin embargo, ¿depende de la implementación de JavaScript? ¿O en la codificación de la página o tal vez en el tipo de contenido?
javascript
string
size
byte
Paul Biggar
fuente
fuente
Respuestas:
String
Los valores no dependen de la implementación, de acuerdo con la Especificación ECMA-262 3rd Edition , cada carácter representa una sola unidad de 16 bits de texto UTF-16 :fuente
Esta función devolverá el tamaño en bytes de cualquier cadena UTF-8 que le pase.
function byteCount(s) { return encodeURI(s).split(/%..|./).length - 1; }
Fuente
Los motores de JavaScript son libres de usar UCS-2 o UTF-16 internamente. La mayoría de los motores que conozco usan UTF-16, pero cualquiera que sea la elección que hayan hecho, es solo un detalle de implementación que no afectará las características del lenguaje.
Sin embargo, el propio lenguaje ECMAScript / JavaScript expone caracteres de acuerdo con UCS-2, no UTF-16.
Fuente
fuente
.split(/%(?:u[0-9A-F]{2})?[0-9A-F]{2}|./)
lugar. Su fragmento falla para las cadenas que se codifican en "% uXXXX".Si está usando node.js, hay una solución más simple usando búferes :
function getBinarySize(string) { return Buffer.byteLength(string, 'utf8'); }
Hay una biblioteca npm para eso: https://www.npmjs.org/package/utf8-binary-cutter (del suyo fielmente)
fuente
Puedes usar el Blob para obtener el tamaño de la cadena en bytes.
Ejemplos:
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) );
fuente
Buffer.from('😂').length
Pruebe esta combinación con el uso de la función unescape js:
const byteAmount = unescape(encodeURIComponent(yourString)).length
Ejemplo de proceso de codificación completa:
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
fuente
unescape
función de JavaScript está obsoleta y no debe usarse para decodificar identificadores uniformes de recursos (URI). Fuenteunescape
no se usa para decodificar URI. Se utiliza para convertir%xx
secuencias en caracteres individuales. ComoencodeURIComponent
codifica una cadena como UTF-8, que representa unidades de código como su carácter ASCII correspondiente o como una%xx
secuencia, la llamadaunescape(encodeURIComponent(...))
da como resultado una cadena binaria que contiene la representación UTF-8 de la cadena original. Llamar.length
correctamente da el tamaño en bytes de la cadena codificada como UTF-8.un
)escape
está en desuso desde 1999, pero todavía está disponible en todos los navegadores ... - Dicho esto, hay buenas razones para desaprobarlo. Básicamente, no hay forma de usarlos correctamente (excepto para codificar / decodificar UTF8 en combinación conen
- /decodeURI
(Component
) - o al menos no conozco ninguna otra aplicación útil para (un
)escape
). Y hoy existen mejores alternativas para codificar / decodificar UTF8 (TextEncoder
, etc.)Tenga en cuenta que si está apuntando a node.js puede usar
Buffer.from(string).length
:var str = "\u2620"; // => "☠" str.length; // => 1 (character) Buffer.from(str).length // => 3 (bytes)
fuente
UTF-8 codifica caracteres utilizando de 1 a 4 bytes por punto de código. Como CMS señaló en la respuesta aceptada, JavaScript almacenará cada carácter internamente usando 16 bits (2 bytes).
Si analiza cada carácter de la cadena a través de un bucle y cuenta el número de bytes utilizados por punto de código, y luego multiplica el recuento total por 2, debe tener el uso de memoria de JavaScript en bytes para esa cadena codificada en UTF-8. Quizás algo como esto:
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; }
Ejemplos:
getStringMemorySize( 'I' ); // 2 getStringMemorySize( '❤' ); // 4 getStringMemorySize( '𠀰' ); // 8 getStringMemorySize( 'I❤𠀰' ); // 14
fuente
Estas son 3 formas en las que uso:
TextEncoder ()
(new TextEncoder().encode("myString")).length)
Gota
new Blob(["myString"]).size)
Buffer
Buffer.byteLength("myString", 'utf8'))
fuente
El tamaño de una cadena de JavaScript es
Pre-ES6
Siempre 2 bytes por carácter. UTF-16 no está permitido porque la especificación dice que "los valores deben ser enteros sin signo de 16 bits". Dado que las cadenas UTF-16 pueden usar caracteres de 3 o 4 bytes, violaría el requisito de 2 bytes. Fundamentalmente, aunque UTF-16 no se puede admitir por completo, el estándar requiere que los caracteres de dos bytes utilizados sean caracteres UTF-16 válidos. En otras palabras, las cadenas de JavaScript anteriores a ES6 admiten un subconjunto de caracteres UTF-16.
ES6 y posterior
2 bytes por carácter, o 5 o más bytes por carácter. Los tamaños adicionales entran en juego porque ES6 (ECMAScript 6) agrega soporte para escapes de puntos de código Unicode . El uso de un escape Unicode se ve así: \ u {1D306}
Notas practicas
Esto no se relaciona con la implementación interna de un motor en particular. Por ejemplo, algunos motores utilizan estructuras de datos y bibliotecas con compatibilidad total con UTF-16, pero lo que proporcionan externamente no tiene por qué ser compatibilidad total con UTF-16. Además, un motor también puede proporcionar soporte UTF-16 externo, pero no está obligado a hacerlo.
Para ES6, prácticamente hablando, los caracteres nunca tendrán más de 5 bytes de longitud (2 bytes para el punto de escape + 3 bytes para el punto de código Unicode) porque la última versión de Unicode solo tiene 136,755 caracteres posibles, que se ajustan fácilmente a 3 bytes. Sin embargo, esto técnicamente no está limitado por el estándar, por lo que, en principio, un solo carácter podría usar, por ejemplo, 4 bytes para el punto de código y 6 bytes en total.
La mayoría de los ejemplos de código aquí para calcular el tamaño de byte no parecen tener en cuenta los escapes de puntos de código Unicode ES6, por lo que los resultados podrían ser incorrectos en algunos casos.
fuente
Buffer.from('test').length
yBuffer.byteLength('test')
igual a 4 (en el Nodo) ynew Blob(['test']).size
también es igual a 4?'\u{1F600}'.length===2
,'\u{1F600}'==='\uD83D\uDE00'
,'\u{1F600}'==='😀'
)Un solo elemento en una cadena de JavaScript se considera una sola unidad de código UTF-16. Es decir, los caracteres de las cadenas se almacenan en 16 bits (1 unidad de código) y 16 bits es igual a 2 bytes (8 bits = 1 byte).
El
charCodeAt()
método se puede utilizar para devolver un número entero entre 0 y 65535 que representa la unidad de código UTF-16 en el índice dado.los
codePointAt()
puede utilizar para devolver el valor de punto de código completo para caracteres Unicode, por ejemplo, UTF-32.Cuando un carácter UTF-16 no se puede representar en una sola unidad de código de 16 bits, tendrá un par sustituto y, por lo tanto, utilizará dos unidades de código (2 x 16 bits = 4 bytes)
Consulte Codificaciones Unicode para conocer las diferentes codificaciones y sus rangos de código.
fuente
La respuesta de Lauri Oherd funciona bien para la mayoría de las cadenas que se ven en la naturaleza, pero fallará si la cadena contiene caracteres solitarios en el rango de pares sustitutos, 0xD800 a 0xDFFF. P.ej
byteCount(String.fromCharCode(55555)) // URIError: URI malformed
Esta función más larga debería manejar todas las cadenas:
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; }
P.ej
bytes(String.fromCharCode(55555)) // 3
Calculará correctamente el tamaño de las cadenas que contienen pares sustitutos:
bytes(String.fromCharCode(55555, 57000)) // 4 (not 6)
Los resultados se pueden comparar con la función incorporada de Node
Buffer.byteLength
:Buffer.byteLength(String.fromCharCode(55555), 'utf8') // 3 Buffer.byteLength(String.fromCharCode(55555, 57000), 'utf8') // 4 (not 6)
fuente
Estoy trabajando con una versión integrada del motor V8. Probé una sola cuerda. Empujando cada paso 1000 caracteres. UTF-8.
Primera prueba con el carácter "A" (hexadecimal: 41) de un solo byte (8 bits, ANSI). Segunda prueba con carácter de dos bytes (16 bits) "Ω" (hexadecimal: CE A9) y la tercera prueba con carácter de tres bytes (24 bits) "☺" (hexadecimal: E2 98 BA).
En los tres casos, el dispositivo imprime sin memoria a 888 000 caracteres y utilizando aprox. 26 348 kb en RAM.
Resultado: los caracteres no se almacenan dinámicamente. Y no con solo 16 bits. - Ok, quizás solo para mi caso (Dispositivo de RAM de 128 MB integrado, motor V8 C ++ / QT) - La codificación de caracteres no tiene nada que ver con el tamaño en RAM del motor javascript. Por ejemplo, encodingURI, etc. solo es útil para la transmisión y el almacenamiento de datos de alto nivel.
Embebidos o no, lo cierto es que los caracteres no solo se almacenan en 16bit. Desafortunadamente, no tengo una respuesta del 100%, lo que Javascript hace en el área de bajo nivel. Por cierto. He probado lo mismo (primera prueba anterior) con una matriz de caracteres "A". Empujó 1000 elementos en cada paso. (Exactamente la misma prueba. Reemplazo de cadena a matriz) Y el sistema saca de memoria (deseado) después de 10 416 KB usando una longitud de matriz de 1 337 000. Entonces, el motor javascript no es simplemente restringido. Es un tipo más complejo.
fuente
Puedes probar esto:
var b = str.match(/[^\x00-\xff]/g); return (str.length + (!b ? 0: b.length));
Funcionó para mí.
fuente