Quantos bytes em uma string JavaScript?

Eu tenho uma cadeia de javascript que é de cerca de 500K quando sendo enviado do servidor em UTF-8. Como posso saber seu tamanho em JavaScript?

Eu sei que JavaScript usa UCS-2, então isso significa 2 bytes por caractere. No entanto, isso depende da implementação do JavaScript? Ou na codificação da página ou talvez no tipo de conteúdo?

    String valores de String não dependem da implementação, de acordo com a especificação da terceira edição do ECMA-262 , cada caractere representa uma única unidade de 16 bits do texto UTF-16 :

    4.3.16 Valor da Sequência

    Um valor de cadeia é um membro do tipo String e é uma sequência ordenada finita de zero ou mais valores inteiros não assinados de 16 bits.

    OBSERVAÇÃO Embora cada valor geralmente represente uma única unidade de 16 bits de texto UTF-16, o idioma não impõe restrições ou requisitos aos valores, exceto que eles são inteiros não assinados de 16 bits.

    Esta function retornará o tamanho do byte de qualquer string UTF-8 que você passar para ela.

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

    Fonte

    Mecanismos JavaScript são livres para usar UCS-2 ou UTF-16 internamente. A maioria dos mecanismos que eu conheço usa o UTF-16, mas qualquer que seja a escolha que eles fizeram, é apenas um detalhe de implementação que não afetará as características do idioma.

    A linguagem ECMAScript / JavaScript em si, no entanto, expõe caracteres de acordo com o UCS-2, não com o UTF-16.

    Fonte

    Se você estiver usando o node.js, há uma solução mais simples usando buffers :

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

    Há um npm lib para isso: https://www.npmjs.org/package/utf8-binary-cutter (do seu fielmente)

    Tente esta combinação com o uso da function unescape js:

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

    Exemplo de processo completo de codificação:

     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 

    Veja a canvas adicional http://sofpt.miximages.com/byte/js_utf_byte_length.png (Sou um novo usuário, portanto não posso usar a tag img)

    O UTF-8 codifica caracteres usando de 1 a 4 bytes por ponto de código. Como o CMS apontou na resposta aceita, o JavaScript armazenará cada caractere internamente usando 16 bits (2 bytes).

    Se você analisar cada caractere na string por meio de um loop e contar o número de bytes usados ​​por ponto de código e, em seguida, multiplicar a contagem total por 2, deverá ter o uso de memory do JavaScript em bytes para essa string codificada em UTF-8. Talvez algo assim:

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

    Exemplos:

     getStringMemorySize( 'I' ); // 2 getStringMemorySize( '❤' ); // 4 getStringMemorySize( '𠀰' ); // 8 getStringMemorySize( 'I❤𠀰' ); // 14 

    Observe que, se você estiver segmentando o node.js, poderá usar o Buffer.from(string).length :

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

    O tamanho de uma string JavaScript é

    • Pre-ES6 : 2 bytes por caractere
    • ES6 e posterior: 2 bytes por caractere ou 5 ou mais bytes por caractere

    Pré-ES6
    Sempre 2 bytes por caractere. UTF-16 não é permitido porque a especificação diz “valores devem ser inteiros não assinados de 16 bits”. Como as strings UTF-16 podem usar caracteres de 3 ou 4 bytes, isso violaria o requisito de 2 bytes. Crucialmente, enquanto o UTF-16 não pode ser totalmente suportado, o padrão requer que os caracteres de dois bytes usados ​​sejam caracteres UTF-16 válidos. Em outras palavras, as strings pré-ES6 JavaScript suportam um subconjunto de caracteres UTF-16.

    ES6 e posterior
    2 bytes por caractere ou 5 ou mais bytes por caractere. Os tamanhos adicionais entram em ação porque o ES6 (ECMAScript 6) adiciona suporte para escapes de pontos de código Unicode . Usar um escape unicode é assim: \ u {1D306}

    Notas práticas

    • Isso não se relaciona com a implementação interna de um determinado mecanismo. Por exemplo, alguns mecanismos usam estruturas de dados e bibliotecas com suporte UTF-16 completo, mas o que eles fornecem externamente não precisa ter suporte UTF-16 completo. Além disso, um mecanismo também pode fornecer suporte UTF-16 externo, mas não é obrigado a fazê-lo.

    • Para ES6, praticamente os caracteres nunca terão mais de 5 bytes de comprimento (2 bytes para o ponto de escape + 3 bytes para o ponto de código Unicode) porque a última versão do Unicode possui apenas 136.755 caracteres possíveis, que se encheckboxm facilmente em 3 bytes. No entanto, isso tecnicamente não é limitado pelo padrão, então, em princípio, um único caractere poderia usar, digamos, 4 bytes para o ponto de código e 6 bytes no total.

    • A maioria dos exemplos de código aqui para calcular o tamanho do byte não parece levar em conta os escapes de ponto de código ES6 Unicode, portanto, os resultados podem estar incorretos em alguns casos.

    A resposta de Lauri Oherd funciona bem para a maioria das strings vistas em estado selvagem, mas falhará se a string contiver caracteres solitários na faixa de par substituto, 0xD800 a 0xDFFF. Por exemplo

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

    Esta function mais longa deve lidar com todas as strings:

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

    Por exemplo

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

    Ele calculará corretamente o tamanho de strings contendo pares substitutos:

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

    Os resultados podem ser comparados com a function Buffer.byteLength do Node Buffer.byteLength :

     Buffer.byteLength(String.fromCharCode(55555), 'utf8') // 3 Buffer.byteLength(String.fromCharCode(55555, 57000), 'utf8') // 4 (not 6) 

    Você pode tentar isto:

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

    Isso funcionou para mim.

    Estou trabalhando com uma versão incorporada do mecanismo V8. Eu testei uma única string. Empurrando cada etapa 1000 caracteres. UTF-8.

    Primeiro teste com byte único (8 bits, ANSI) Caractere “A” (hexadecimal: 41). Segundo teste com caractere de dois bytes (16 bits) “Ω” (hexadecimal: CE A9) e o terceiro teste com caractere de três bytes (24 bits) “☺” (hex: E2 98 BA).

    Nos três casos, o dispositivo imprime fora da memory em 888 000 caracteres e usando ca. 26 348 kb em RAM.

    Resultado: os caracteres não são armazenados dinamicamente. E não com apenas 16 bits. – Ok, talvez apenas para o meu caso (Embedded 128 MB de RAM, V8 Engine C ++ / QT) – A codificação de caracteres não tem nada a ver com o tamanho da ram do mecanismo de javascript. Por exemplo, encodingURI, etc. é útil apenas para transmissão e armazenamento de dados de alto nível.

    Incorporado ou não, o fato é que os personagens não são armazenados apenas em 16 bits. Infelizmente eu não tenho 100% de resposta, o que o JavaScript faz na área de baixo nível. Btw. Eu testei o mesmo (primeiro teste acima) com uma matriz de caractere “A”. Empurrou 1000 itens a cada passo. (Exatamente o mesmo teste. Apenas substituído string para matriz) E o sistema traz de memory (queria) após 10 416 KB usando e comprimento de matriz de 1 337 000. Assim, o mecanismo de javascript não é simples restrito. É um tipo mais complexo.

    Um único elemento em uma String JavaScript é considerado uma unidade de código UTF-16 única. Ou seja, os caracteres Strings são armazenados em 16 bits (1 unidade de código) e 16 bits é igual a 2 bytes (8 bits = 1 byte).

    O método charCodeAt() pode ser usado para retornar um inteiro entre 0 e 65535 representando a unidade de código UTF-16 no índice fornecido.

    O codePointAt() pode ser usado para retornar o valor inteiro do ponto de código para caracteres Unicode, por exemplo, UTF-32.

    Quando um caractere UTF-16 não pode ser representado em uma única unidade de código de 16 bits, ele terá um par substituto e, portanto, usará duas unidades de código (2 x 16 bits = 4 bytes)

    Veja codificações Unicode para diferentes codificações e seus intervalos de código.