TGStat
TGStat
Type to search
Advanced channel search
  • flag English
    Site language
    flag Russian flag English flag Uzbek
  • Sign In
  • Catalog
    Channels and groups catalog Regional compilations Thematic compilations Платные каналы Search for channels
    Add a channel/group
  • Ratings
    Rating of channels Rating of groups Posts rating
    Ratings of brands and people
  • Analytics
  • Search by posts
  • Telegram monitoring
  • Promotion
    Advertising through Yandex Business Advertising in channels through TGStat Agency Advertising on TGStat.ru website
Настя Котова // Frontend & Node.js

24 Aug, 18:25

Open in Telegram Share Report

Весной мы обсуждали работу с сырыми данными: ArrayBuffer, Buffer в Node.js, SharedArrayBuffer и Blob. Но кое-какие инструменты мы тогда не обсудили, а именно TextEncoder и TextDecoder, пару, которая переводит строки в байты и обратно.

API у них достаточно простое: у одного есть encode(), у другого decode(). Однако своих нюансов в их работу добавляет то, что строки в JavaScript хранятся в UTF-16, а данные вокруг (файлы, сеть и т.д.) почти всегда в UTF-8. Поэтому TextEncoder умеет кодировать только в UTF-8, и других вариантов у него нет, а вот TextDecoder принимает десятки кодировок.

Дальше начинаются суррогатные пары. Символы выше U+FFFF (эмодзи, редкие иероглифы, некоторые математические знаки) не помещаются в один 16-битный код и хранятся как два. Отдельного внимания заслуживает случай, когда суррогат остался без пары, например, строку обрезали ровно посередине символа. Тогда TextEncoder заменит его на U+FFFD (тот самый знаменитый �) и не выбросит никакого исключения.

Дело в том, что в спецификации encode() принимает USVString — строку, в которой суррогатов не бывает по определению. Обычные JS-строки — это DOMString, и при передаче аргумента происходит конвертация одного в другое, при которой каждый одинокий суррогат и заменяется. Таким образом до самого кодировщика битая строка уже не доходит.

Похожая тихая механика, без всяких ошибок, есть и у BOM — метки порядка байтов U+FEFF, которую любят добавлять в начало файла редакторы под Windows. По умолчанию TextDecoder её срезает, и в результирующей строке она не появляется. Опция ignoreBOM работает противоположно тому, что можно предположить по названию: она означает не «игнорировать метку», а «не обрабатывать её специальным образом», то есть оставить в строке как обычный символ.

Последний нюанс касается потокового чтения. Если данные приходят чанками, многобайтовый символ вполне может оказаться разрезанным на границе. Стандартный вызов декодера посчитает такую последовательность некорректной и выдаст всё тот же символ �. Однако если передать { stream: true }, то декодер сохранит незавершённый хвост до следующего вызова, а финальный decode() без аргументов сбросит остаток.


const decoder = new TextDecoder();
decoder.decode(chunk, { stream: true });
decoder.decode();

1.5k 0 8 4 19
Catalog
Channels and groups catalog Channels compilations Search for channels Add a channel/group
Ratings
Rating of Telegram channels Rating of Telegram groups Posts rating Ratings of brands and people
API
API statistics Search API of posts API Callback
Our channels
@TGStat @TGStat_Chat @telepulse @TGStatAPI
Read
Академия TGStat Telegram Research 2019 Telegram Research 2021 Telegram Research 2023
Contacts
Справочный центр Support Email Jobs
Miscellaneous
Terms and conditions Privacy policy Public offer
Our bots
@TGStat_Bot @SearcheeBot @TGAlertsBot @tg_analytics_bot @TGStatChatBot