Home > Blog > Desenvolvimento Web
Desenvolvimento Web
JavaScript
Programação

TextEncoder e TextDecoder no Node.js

Atualizado em: 15 de agosto de 2026

Terminal Linux usado em desenvolvimento e administração de aplicações Node.js

Aplicações Node.js trabalham com arquivos, redes, APIs, bancos e protocolos que transportam bytes, não strings abstratas. O TextEncoder e TextDecoder no Node.js fazem a ponte entre texto JavaScript e dados binários usando interfaces padronizadas da Web.

TextEncoder converte strings para bytes UTF-8. TextDecoder converte ArrayBuffer, Buffer ou TypedArray para texto, com suporte a codificações, streaming e tratamento de sequências inválidas. Essas APIs são úteis em fetch, Web Streams, criptografia, sockets, arquivos e Worker Threads.

Neste guia, você aprenderá a codificar e decodificar, lidar com Unicode, chunks divididos, BOM, fatal errors, encodeInto, Buffer, streams, limites e testes.

O que são TextEncoder e TextDecoder?

São APIs padronizadas para conversão entre texto e bytes. A documentação oficial de TextEncoder no Node.js mostra métodos e propriedades. A documentação de TextDecoder na MDN explica decodificação, streaming e opções.

Para dados binários, consulte Buffer no Node.js. Para fluxos de texto, veja Web Streams API no Node.js. O artigo String Decoder no Node.js apresenta a API tradicional para streams.

TextEncoder básico

const encoder = new TextEncoder();
const bytes = encoder.encode('Olá, Node.js!');

console.log(bytes);

O resultado é um Uint8Array em UTF-8. TextEncoder padronizado usa UTF-8.

Tamanho em bytes

const text = 'ação';
const bytes = encoder.encode(text);

console.log(text.length);
console.log(bytes.byteLength);

O comprimento da string mede unidades UTF-16, enquanto byteLength mede bytes UTF-8. Caracteres acentuados e emojis ocupam vários bytes.

TextDecoder básico

const decoder = new TextDecoder('utf-8');
const text = decoder.decode(bytes);

Se nenhuma codificação for informada, UTF-8 é usada na maioria dos casos.

Decodificando Buffer

const buffer = Buffer.from('Olá', 'utf8');
const text = decoder.decode(buffer);

Buffer é uma subclasse de Uint8Array e pode ser passado diretamente.

encodeInto()

const destination = new Uint8Array(1024);
const result = encoder.encodeInto(
  'mensagem importante',
  destination
);

console.log(result.read);
console.log(result.written);

encodeInto() escreve em um buffer fornecido, reduzindo alocações em loops de alta frequência.

Buffer pequeno

Quando o destino não cabe, apenas parte da string é consumida:

const destination = new Uint8Array(5);
const result = encoder.encodeInto('abcdef', destination);

Use read e written para continuar sem cortar pares substitutos incorretamente.

Unicode e surrogate pairs

JavaScript representa strings em UTF-16. Emojis e alguns símbolos usam duas unidades de código. TextEncoder converte para a sequência UTF-8 apropriada.

const bytes = encoder.encode('🚀');

Não divida strings arbitrariamente por índice quando precisa preservar caracteres completos.

Sequências inválidas

TextDecoder pode substituir bytes inválidos pelo caractere de substituição:

const invalid = new Uint8Array([0xff, 0xfe]);
const text = new TextDecoder().decode(invalid);

Modo fatal

const decoder = new TextDecoder('utf-8', {
  fatal: true
});

try {
  decoder.decode(invalid);
} catch (error) {
  console.error('UTF-8 inválido');
}

Use fatal quando dados corrompidos precisam gerar erro em vez de substituição silenciosa.

BOM

Byte Order Mark pode aparecer no início de arquivos. TextDecoder possui opção relacionada a BOM:

const decoder = new TextDecoder('utf-8', {
  ignoreBOM: false
});

Teste conforme o formato. Um BOM inesperado pode alterar chaves ou o primeiro valor analisado.

Decodificação em chunks

Um caractere UTF-8 pode ser dividido entre chunks. Use stream: true:

const decoder = new TextDecoder();
let output = '';

for (const chunk of chunks) {
  output += decoder.decode(chunk, {
    stream: true
  });
}

output += decoder.decode();

A chamada final sem bytes libera qualquer estado restante.

Erro ao decodificar cada chunk isoladamente

for (const chunk of chunks) {
  output += new TextDecoder().decode(chunk);
}

Esse padrão pode inserir caracteres de substituição quando uma sequência multibyte está dividida.

TextDecoderStream

const textStream = byteStream.pipeThrough(
  new TextDecoderStream('utf-8', {
    fatal: true
  })
);

TextDecoderStream mantém estado entre chunks e integra com Web Streams.

TextEncoderStream

const byteStream = textStream.pipeThrough(
  new TextEncoderStream()
);

É útil para transformar strings em bytes antes de enviar para fetch ou arquivo.

Arquivo em memória

const fs = require('node:fs/promises');

const bytes = await fs.readFile('./message.txt');
const text = new TextDecoder('utf-8', {
  fatal: true
}).decode(bytes);

readFile() carrega todo o arquivo. Para arquivos grandes, use stream.

Arquivo em stream

Converta o stream tradicional ou use StringDecoder. O importante é manter estado entre chunks e aplicar limite de tamanho.

Veja File System no Node.js.

Fetch

const response = await fetch(url);

for await (const chunk of response.body) {
  // chunks binários
}

Para texto grande, use TextDecoderStream em vez de response.text(), que acumula tudo.

Consulte Fetch Nativo no Node.js.

Protocolos de linha

Depois de decodificar corretamente, acumule apenas até encontrar delimitador:

let pending = '';

for await (const chunk of textStream) {
  pending += chunk;

  let index;
  while ((index = pending.indexOf('\n')) !== -1) {
    const line = pending.slice(0, index);
    pending = pending.slice(index + 1);
    processLine(line);
  }

  if (pending.length > MAX_LINE_LENGTH) {
    throw new Error('Linha muito longa');
  }
}

JSON em stream

JSON comum exige documento completo. Para fluxos grandes, use NDJSON ou parser incremental com limites.

Criptografia

const data = new TextEncoder().encode(message);
const digest = await crypto.subtle.digest(
  'SHA-256',
  data
);

Use a mesma codificação em todos os sistemas. Veja Web Crypto API no Node.js.

Assinaturas

Uma diferença de normalização Unicode ou final de linha altera bytes e assinatura. Protocolos precisam definir a representação exata.

Normalização Unicode

const normalized = input.normalize('NFC');
const bytes = encoder.encode(normalized);

Não normalize automaticamente se o protocolo exige bytes originais.

Outras codificações

TextDecoder pode aceitar codificações além de UTF-8 conforme suporte:

const decoder = new TextDecoder('windows-1252');

TextEncoder continua produzindo UTF-8. Para gerar outra codificação, use biblioteca ou API específica.

Codificação desconhecida

Dados sem charset não podem ser decodificados com certeza. Use metadados confiáveis, heurística limitada ou rejeite entrada ambígua.

Content-Type

Um header pode declarar charset:

text/plain; charset=utf-8

Não confie cegamente no header de origem desconhecida. Aplique limites e modo fatal quando necessário.

Performance

Reutilize instâncias de TextEncoder e TextDecoder quando apropriado. Em decodificação streaming, uma instância representa o estado de um fluxo e não deve ser compartilhada entre fluxos concorrentes.

Concorrência

Crie um decoder por arquivo, socket ou resposta. Misturar chunks de origens diferentes corrompe o estado.

Memória

Concatenar strings repetidamente pode criar cópias. Processe linhas ou registros e descarte conteúdo já consumido.

Limites

  • tamanho total de texto;
  • tamanho por linha;
  • quantidade de registros;
  • tempo de leitura;
  • profundidade de parsing posterior.

Worker Threads

TypedArrays podem ser transferidos para workers para processamento pesado. Veja Worker Threads no Node.js. Não transfira um ArrayBuffer que ainda será usado na thread original.

Testes

Cubra:

  • ASCII;
  • acentos;
  • emoji;
  • sequência dividida;
  • UTF-8 inválido;
  • BOM;
  • arquivo vazio;
  • linha longa;
  • encodeInto parcial;
  • charset alternativo.

Erros comuns

  • Assumir um byte por caractere: tamanhos ficam incorretos.
  • Decodificar chunks isolados: Unicode é corrompido.
  • Ignorar bytes inválidos: dados inconsistentes passam.
  • Compartilhar decoder entre fluxos: estados se misturam.
  • Carregar arquivo gigante: memória cresce.
  • Assinar strings sem codificação definida: sistemas divergem.
  • Não finalizar decode: bytes pendentes não são processados.

Boas práticas

  • Defina UTF-8 explicitamente.
  • Use stream para chunks.
  • Crie um decoder por fluxo.
  • Use fatal em formatos estritos.
  • Finalize a decodificação.
  • Limite linhas e total.
  • Reutilize encoder.
  • Use encodeInto em caminhos críticos.
  • Teste Unicode dividido.
  • Documente normalização.

Conclusão

O TextEncoder e TextDecoder no Node.js oferecem conversão padronizada entre strings e bytes, com integração a fetch, Web Streams, criptografia e Worker Threads.

O ponto crítico é lembrar que texto e bytes não têm correspondência simples. Unicode pode ocupar vários bytes e sequências podem atravessar chunks. Com streaming, modo fatal, limites e uma codificação definida, aplicações evitam corrupção silenciosa e processam texto binário de forma previsível.

Os 10 Melhores Cursos de Programação de 2026

Descubra os melhores cursos de programação. Aprenda a escolher o curso ideal para iniciar ou avançar na carreira de desenvolvedor

POSTS RELACIONADOS

Ver todos

Seta para a direita