TextEncoder: метод encodeInto()
Базовая версия Широко доступна
Эта функция хорошо отработана и работает на многих устройствах и версиях браузеров. Она доступна в браузерах с января 2020 года.
Примечание: Эта функция доступна в Web Workers.
Метод TextEncoder.encodeInto() принимает строку для кодирования и целевой Uint8Array для размещения результирующего кодированного UTF-8 текста, и возвращает объект, указывающий на ход кодирования. Этот метод потенциально более производителен, чем устаревший метод encode() — особенно когда целевой буфер является представлением кучи Wasm.
Синтаксис
encodeInto(string, uint8Array)
Параметры
string-
Строка, содержащая текст для кодирования.
uint8Array-
Экземпляр объекта
Uint8Arrayдля размещения результирующего кодированного UTF-8 текста.
Возвращаемое значение
Объект, содержащий два члена:
read-
Количество единиц UTF-16 кода из исходного текста, преобразованных в UTF-8. Это может быть меньше, чем
string.length, если вuint8Arrayне было достаточно места. written-
Количество изменённых байтов в целевом
Uint8Array. Гарантируется, что записанные байты образуют полные последовательности байтов UTF-8.
Кодирование в определённую позицию
encodeInto() всегда помещает свой вывод в начало массива. Однако иногда полезно начать вывод с определённого индекса. Для этого используется TypedArray.prototype.subarray():
const encoder = new TextEncoder();
function encodeIntoAtPosition(string, u8array, position) {
return encoder.encodeInto(
string,
position ? u8array.subarray(position | 0) : u8array,
);
}
const u8array = new Uint8Array(8);
encodeIntoAtPosition("hello", u8array, 2);
console.log(u8array.join()); // 0,0,104,101,108,108,111,0
Размер буфера
Для преобразования строки JavaScript s, необходимое пространство для полного преобразования никогда не будет меньше s.length байтов и никогда не будет больше s.length * 3 байтов. Точное соотношение длин UTF-8 и UTF-16 для вашей строки зависит от языка, с которым вы работаете:
- Для простого английского текста, использующего в основном символы ASCII, соотношение близко к 1.
- Для текста на скриптах, использующих символы от U+0080 до U+07FF (включая греческий, кириллический, иврит, арабский и др.), соотношение составляет примерно 2.
- Для текста на скриптах, использующих символы от U+0800 до U+FFFF (включая китайский, японский, корейский и др.), соотношение составляет примерно 3.
- Встречается редко, но бывают ситуации, когда текст целиком написан на скриптах с символами вне основного диапазона кодов (хотя они существуют). Эти символы обычно являются математическими символами, эмодзи, историческими письменностями и т. д. Соотношение для таких символов составляет 2, так как они занимают 4 байта в UTF-8 и 2 байта в UTF-16.
Если выделенная память (обычно в куче Wasm) ожидается кратковременной, имеет смысл выделить s.length * 3 байта для вывода, в этом случае первая попытка преобразования гарантированно преобразует всю строку.
Например, если ваш текст в основном английский, маловероятно, что длинный текст превысит s.length * 2 байтов в длину. Таким образом, более оптимистичный подход может заключаться в выделении s.length * 2 + 5 байтов и выполнении перевыделения в редком случае, если оптимистичный прогноз оказался неверным.
Если выход ожидается долгоживущим, имеет смысл вычислить минимальный размер выделения roundUpToBucketSize(s.length), максимальный размер выделения s.length * 3, и выбрать (как компромисс между использованием памяти и скоростью) порог t, такой что если roundUpToBucketSize(s.length) + t >= s.length * 3, вы выделяете память для s.length * 3. В противном случае сначала выделяете память для roundUpToBucketSize(s.length) и выполняете преобразование. Если элемент read в возвращаемом словаре равен s.length, преобразование выполнено. Если нет, перевыделяете целевой буфер на written + (s.length - read) * 3 и затем преобразуете остаток, взяв подстроку s, начиная с индекса read, и подбуфер целевого буфера, начиная с индекса written.
Выше roundUpToBucketSize() — это функция, которая округляет до размера блока выделения памяти. Например, если ваш выделения памяти Wasm используют блоки размером степени двойки, roundUpToBucketSize() должна возвращать аргумент, если он является степенью двойки, или следующей степенью двойки в противном случае. Если поведение выделения памяти Wasm неизвестно, roundUpToBucketSize() должна быть идентичной функцией.
Если поведение вашего выделения памяти неизвестно, вы можете выполнить до двух перевыделений и заставить первое перевыделение умножить оставшуюся непреобразованную длину на два вместо трёх. Однако в этом случае имеет смысл не реализовывать обычное умножение длины уже записанного буфера на два, потому что в таком случае, если произошло второе перевыделение, оно всегда будет перевыделять больше, чем исходная длина, умноженная на три. Приведенные рекомендации предполагают, что вам не нужно выделять место для нулевого терминатора. То есть, в стороне Wasm вы работаете с строками Rust или не нуль-терминирующим классом C++. Если вы работаете с C++ строками std::string, даже если вам показана логическая длина, вам нужно учитывать дополнительный байт терминатора при вычислении округления до размера блока выделения памяти. См. следующий раздел о C-строках.
Отсутствие нуль-терминации
Если входная строка содержит символ U+0000, encodeInto() запишет байт 0x00 в выходной поток. encodeInto() не записывает байт-маркер 0x00 в стиле C после логического выхода.
Если ваша программа Wasm использует C-строки, вам необходимо записать 0x00 маркер, и вы не можете предотвратить отображение логически усечённой строки вашей программой Wasm, если в строке JavaScript содержался U+0000. Обратите внимание:
const encoder = new TextEncoder();
function encodeIntoWithSentinel(string, u8array, position) {
const stats = encoder.encodeInto(
string,
position ? u8array.subarray(position | 0) : u8array,
);
if (stats.written < u8array.length) u8array[stats.written] = 0; // append null if room
return stats;
}
Примеры
<p class="source">This is a sample paragraph.</p> <p class="result"></p>
const sourcePara = document.querySelector(".source");
const resultPara = document.querySelector(".result");
const string = sourcePara.textContent;
const textEncoder = new TextEncoder();
const utf8 = new Uint8Array(string.length);
const encodedResults = textEncoder.encodeInto(string, utf8);
resultPara.textContent +=
`Bytes read: ${encodedResults.read}` +
` | Bytes written: ${encodedResults.written}` +
` | Encoded result: ${utf8}`;
Спецификации
| Спецификация |
|---|
| Кодирование # ref-for-dom-textencoder-encodeinto① |
Совместимость с браузерами
| Рабочие столы | Мобильные устройства | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari на iOS | Samsung Internet | WebView Android | |
encodeInto |
74 | 79 | 66 | 62 | 14.1 | 74 | 66 | 50 | 14.5 | 11.0 | 74 |
См. также
- Интерфейс
TextEncoder, к которому он относится. TextEncoder.encode()
© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder/encodeInto