No meu código JavaScript, preciso escrever uma mensagem para o servidor neste formato:
<size in bytes>CRLF
<data>CRLF
Exemplo:
3
foo
Os dados podem conter caracteres Unicode. Preciso enviá-los como UTF-8.
Estou procurando a maneira mais cruzada de navegadores de calcular o comprimento da string em bytes em JavaScript.
Eu tentei isso para compor minha carga útil:
return unescape(encodeURIComponent(str)).length + "\n" + str + "\n"
Mas não me dá resultados precisos para os navegadores mais antigos (ou, talvez, as strings nesses navegadores em UTF-16?).
Alguma pista?
Atualizar:
Exemplo: o comprimento em bytes da string ЭЭХ! Naïve?
em UTF-8 é 15 bytes, mas alguns navegadores relatam 23 bytes.
javascript
unicode
Alexander Gladysh
fonte
fonte
Respostas:
Não há como fazer isso nativamente em JavaScript.(Veja a resposta de Riccardo Galli para uma abordagem moderna.)Para referência histórica ou onde APIs de TextEncoder ainda não estão disponíveis .
Se você conhece a codificação de caracteres, pode calculá-la sozinho.
encodeURIComponent
assume UTF-8 como a codificação de caracteres, então se você precisa dessa codificação, você pode fazer,Isso deve funcionar devido à maneira como o UTF-8 codifica sequências de bytes múltiplos. O primeiro byte codificado sempre começa com um bit alto de zero para uma única sequência de bytes ou um byte cujo primeiro dígito hexadecimal é C, D, E ou F. O segundo e subsequentes bytes são aqueles cujos primeiros dois bits são 10 Esses são os bytes extras que você deseja contar em UTF-8.
A tabela na wikipedia torna isso mais claro
Se, em vez disso, você precisa entender a codificação da página, pode usar este truque:
fonte
lengthInUtf8Bytes
função retorna 5 para caracteres não BMP comostr.length
para esses retornos 2. Escreverei uma versão modificada dessa função na seção de respostas.encodeURIComponent('🍀')
é'%F0%9F%8D%80'
.Anos se passaram e hoje você pode fazer isso nativamente
Observe que ainda não é compatível com o IE (ou Edge) (você pode usar um polyfill para isso).
Documentação MDN
Especificações padrão
fonte
TextEncode
suporta apenas utf-8 desde o Chrome 53.Esta é uma versão muito mais rápida, que não usa expressões regulares, nem encodeURIComponent () :
Aqui está uma comparação de desempenho .
Ele apenas calcula o comprimento em UTF8 de cada ponto de código Unicode retornado por charCodeAt () (com base nas descrições da wikipedia de UTF8 e caracteres substitutos de UTF16).
Ele segue a RFC3629 (em que os caracteres UTF-8 têm no máximo 4 bytes).
fonte
Para codificação UTF-8 simples, com compatibilidade ligeiramente melhor do que
TextEncoder
, Blob resolve. Não funciona em navegadores muito antigos.fonte
Esta função retornará o tamanho de byte de qualquer string UTF-8 que você passar para ela.
Fonte
fonte
ユーザーコード
comprimento errado em bytes é sempre 21, testei em diferentes ferramentas; seja mais gentil com seus comentários;)Outra abordagem muito simples usando
Buffer
(apenas para NodeJS):fonte
Buffer.byteLength(string, 'utf8')
.Demorei um pouco para encontrar uma solução para o React Native, então vou colocá-la aqui:
Primeiro instale o
buffer
pacote:Em seguida, use o método do nó:
fonte
Na verdade, descobri o que há de errado. Para que o código funcione, a página
<head>
deve ter esta tag:Ou, como sugerido nos comentários, se o servidor enviar o
Content-Encoding
cabeçalho HTTP , ele também deve funcionar.Então, os resultados de diferentes navegadores são consistentes.
Aqui está um exemplo:
Observação: suspeito que a especificação de qualquer codificação (precisa) resolveria o problema de codificação. É apenas uma coincidência eu precisar do UTF-8.
fonte
unescape
função JavaScript não deve ser usada para decodificar Uniform Resource Identifiers (URI).unescape
realmente nunca deve ser usado para decodificar URIs. No entanto, para converter texto em UTF-8 funciona bemunescape(encodeURIComponent(...)).length
sempre calcula o comprimento correto com ou semmeta http-equiv ... utf8
. Sem uma especificação de codificação, alguns navegadores podem simplesmente ter um texto diferente (depois de codificar os bytes do documento em texto html real) cujo comprimento eles calcularam. Pode-se testar isso facilmente, imprimindo não apenas o comprimento, mas também o próprio texto.Aqui está um método independente e eficiente para contar bytes UTF-8 de uma string.
Observe que o método pode gerar erro se uma string de entrada for UCS-2 malformada
fonte
No NodeJS,
Buffer.byteLength
é um método especificamente para este propósito:Observe que, por padrão, o método assume que a string está na codificação UTF-8. Se uma codificação diferente for necessária, passe-a como o segundo argumento.
fonte
strLengthInBytes
apenas sabendo a 'contagem' de caracteres dentro da string? ievar text = "Hello World!; var text_length = text.length; // pass text_length as argument to some method?
. E, apenas para referência, reBuffer
- acabei de encontrar esta resposta que discutenew Blob(['test string']).size
e, no nóBuffer.from('test string').length
,. Talvez ajudem algumas pessoas também?Isso funcionaria para caracteres BMP e SIP / SMP.
fonte
Você pode tentar isto:
Funciona para mim.
fonte