JavaScript TextDecoder и TextEncoder
В этой главе мы рассмотрим встроенные объекты TextDecoder и TextEncoder, которые сделают работу с текстом в JavaScript более эффективной.
Освоение интерфейсов TextEncoder и TextDecoder в JavaScript необходимо для эффективной работы с текстовыми данными, особенно в приложениях, которые работают с необработанными двоичными данными и различными кодировками символов. В этом руководстве объясняется, что делают эти интерфейсы, когда они действительно нужны и как правильно их использовать — с выполняемыми примерами и практическими нюансами.
Что рассматривается на этой странице
- Что означают кодирование и декодирование текста и почему нельзя просто трактовать байты как символы.
- Кодирование строк в байты с помощью
TextEncoder(только UTF-8). - Декодирование байтов обратно в строки с помощью
TextDecoder, включая кодировки, отличные от UTF-8. - Потоковая обработка, обработка ошибок (
fatal) и реальный пример сfetch.
Введение в кодирование и декодирование текста
JavaScript string — это последовательность символов, однако сеть, файловая система и большинство двоичных API работают с байтами. Кодирование текста преобразует символы в байты по определённой схеме (например, UTF-8); декодирование текста выполняет обратную операцию, превращая байты обратно в символы. Одна и та же строка может давать разные последовательности байт в зависимости от кодировки, поэтому декодеру необходимо знать, в какой кодировке были записаны байты.
JavaScript предоставляет два встроенных интерфейса для этого: TextEncoder (string → байты) и TextDecoder (байты → string). Они используются при работе с необработанными двоичными данными — чтении Blob, обработке ArrayBuffer или потоковой передаче ответа из Fetch API.
Использование TextEncoder в JavaScript
Интерфейс TextEncoder в JavaScript преобразует текст из строки в поток закодированных байт. Он поддерживает исключительно кодировку UTF-8 и не принимает параметров кодировки в конструкторе.
Базовый пример кодирования текста
Чтобы закодировать строку с помощью TextEncoder, воспользуйтесь этим простым примером:
Этот скрипт выводит Uint8Array, показывающий UTF-8 кодированную версию строки "Hello, world!". Каждое число — это один байт: 72 — это H, 101 — это e и так далее. Этот массив представляет собой двоичные данные, которые можно передавать по сетевым протоколам или сохранять для дальнейшего использования. Обратите внимание, что конструктор не принимает аргументов — TextEncoder всегда производит только UTF-8.
Продвинутые техники кодирования
Работа с нестандартными символами
TextEncoder легко обрабатывает весь диапазон Unicode. Многобайтовые символы (китайские иероглифы, эмодзи, буквы с диакритическими знаками) разворачиваются в несколько байт каждый — именно поэтому длина в байтах закодированной строки обычно больше её .length:
Это показывает, что TextEncoder преобразует любой символ, представимый в UTF-8, включая эмодзи и специальные символы, и что нельзя предполагать соответствие один символ — один байт.
Использование TextDecoder в JavaScript
В то время как TextEncoder преобразует строки в байты, TextDecoder выполняет обратную операцию — превращает закодированные байтовые данные обратно в читаемые строки. Он поддерживает несколько кодировок, но по умолчанию использует UTF-8.
Базовый пример декодирования текста
Вот как можно декодировать байтовые данные обратно в строку:
Аргументом decode() может быть Uint8Array, любой другой TypedArray, ArrayBuffer или DataView — любой объект, оборачивающий необработанные байты.
Этот код преобразует Uint8Array обратно в строку "Hello, world!", иллюстрируя базовую функциональность TextDecoder.
Декодирование с различными кодировками
Пример с использованием ISO-8859-1
В отличие от TextEncoder, который работает только с UTF-8, TextDecoder может читать многие устаревшие кодировки. Передайте метку кодировки (например, "iso-8859-1", "windows-1252" или "utf-16le") в конструктор:
Вывод — "Hello, Monde!", что демонстрирует работу с байтовыми потоками в кодировке, отличной от UTF-8 — это полезно при чтении файлов, созданных более старыми системами или инструментами без поддержки Unicode.
Лучшие практики кодирования и декодирования
Обеспечение целостности текста
При кодировании и декодировании текста убедитесь, что текст правильно и полностью передаётся или сохраняется. Всегда проверяйте, что закодированные байтовые данные без потерь преобразуются обратно в исходный текст.
Потоковое декодирование по частям
Многобайтовый символ может быть разделён между двумя порциями данных, поступающими по сети. Декодирование каждой порции по отдельности приведёт к искажению символа на границе. Параметр { stream: true } указывает декодеру удерживать любую неполную завершающую последовательность и добавлять её к следующей порции. Вызовите decode() в конце без аргументов для сброса буфера:
Без { stream: true } эта разделённая последовательность байт декодировалась бы в символы замены (U+FFFD), и исходный символ 你 был бы потерян.
Обработка ошибок с помощью fatal
По умолчанию TextDecoder заменяет недопустимые последовательности байт символом замены (U+FFFD, отображается как �) вместо выброса исключения. Чтобы включить строгую валидацию и выбрасывать TypeError при некорректном вводе, передайте { fatal: true }:
Используйте fatal: true, когда необходимо отклонять повреждённые данные; используйте поведение по умолчанию (с потерями), когда частичное отображение предпочтительнее сбоя.
Практический пример: декодирование потока ответа Fetch
Наиболее распространённое практическое применение TextDecoder — побайтовое чтение потокового тела HTTP-ответа. В сочетании с параметром { stream: true } он безопасно собирает текст даже тогда, когда символы пересекают границы порций. Приведённый ниже фрагмент симулирует двухпорционный поток, чтобы работать в любой среде:
В реальном коде вы получали бы эти порции из response.body.getReader() после вызова fetch, что также используется при отслеживании прогресса загрузки.
Когда использовать TextEncoder и TextDecoder
- Чтение или запись содержимого Blob или File в виде необработанных байт.
- Непосредственная работа с ArrayBuffer или типизированным массивом.
- Пообработная обработка потокового сетевого ответа.
- Вычисление длины в байтах (для заголовков
Content-Length), когда количества символов недостаточно.
Как правило, они не нужны для обычных JSON или текста, получаемых через response.json() / response.text() — в этих случаях браузер самостоятельно выполняет декодирование.
Заключение
TextEncoder и TextDecoder — это мост между JavaScript string и необработанными байтами, используемыми двоичными API, сетью и файловой системой. Запомните главное: TextEncoder работает только с UTF-8 и не принимает параметров; TextDecoder поддерживает множество кодировок и предлагает { stream: true } для потоковых данных и { fatal: true } для строгой валидации. Имея эти инструменты в арсенале, вы сможете корректно работать с текстом в любой кодировке и из любого источника данных.