loading
Note:
Why this and not System.Text.Encoding .NET carries only the Unicode encodings by default. Everything else - the code pages a Japanese ERP export or an old Windows share is written in - needs the System.Text.Encoding.CodePages package plus a registration call, and its data is dead weight in a published WebAssembly app. The browser already implements every label in the encoding standard, so borrowing its decoder is usually the shorter path. Encoding is the other way round: TextEncoder only ever produces UTF-8, which .NET does perfectly well on its own.

Support check

IsSupported / IsEncodingSupported / GetCanonicalName

IsSupported says the runtime has TextDecoder at all. IsEncodingSupported asks about one label - there is no list of encodings anywhere in the platform, so it is answered by constructing a decoder and seeing whether it throws. GetCanonicalName normalizes an alias: 'sjis' and 'shift-jis' both come back as 'shift_jis'.

C#
@inject Bit.Butil.TextEncoding textEncoding

var supported = await textEncoding.IsSupported();
var canDecode = await textEncoding.IsEncodingSupported("shift_jis");
var name = await textEncoding.GetCanonicalName("sjis");   // "shift_jis"
Live sample
support check output
Results will appear here when you interact with the samples.

Decode legacy bytes

Decode

The whole point of the class. Each sample below is the same greeting written in a different code page - bytes that are meaningless as UTF-8. Decode them with the right label and they read correctly; decode them as UTF-8 and you get the mojibake every legacy import starts with.

C#
var text = await textEncoding.Decode(bytes, "shift_jis");

// Guessing at the encoding? Turn on fatal and a wrong guess
// comes back as null instead of as replacement characters:
var strict = await textEncoding.Decode(bytes, "shift_jis", fatal: true);
Live sample
decode output
Results will appear here when you interact with the samples.

Encode, and measure

Encode / GetUtf8ByteLength

TextEncoder produces UTF-8 and nothing else - there is no legacy encoder in the platform, by design. GetUtf8ByteLength answers the length question without moving the bytes across the interop boundary, which is what a check against a server-side limit actually needs.

C#
var bytes = await textEncoding.Encode("héllo");     // byte[]
var length = await textEncoding.GetUtf8ByteLength("héllo");   // 6, not 5
Live sample
encode output
Results will appear here when you interact with the samples.

Decode a stream in chunks

CreateDecoder / TextDecoderHandle

Content that arrives a chunk at a time - a download, a fetch body, a file read piece by piece - can split a multi-byte character across two chunks. Decoding each chunk on its own turns that character into replacement characters; a streaming decoder holds the incomplete sequence until the next chunk completes it. The demo splits the Shift_JIS sample straight through the middle of a character to show the difference.

C#
await using var decoder = await textEncoding.CreateDecoder("shift_jis");

foreach (var chunk in chunks)
{
    text += await decoder.Decode(chunk);   // more: true is the default
}

text += await decoder.Flush();             // emits anything still pending
Live sample
streaming output
Results will appear here when you interact with the samples.

API reference

Member
Signature
Description
IsSupported
ValueTask<bool> IsSupported()
True when the runtime exposes TextDecoder. Returns default (false) during prerender/SSR instead of throwing.
IsEncodingSupported
ValueTask<bool> IsEncodingSupported(string label)
True when this runtime can decode that label - any name or alias from the encoding standard's table.
GetCanonicalName
ValueTask<string?> GetCanonicalName(string label)
The canonical name of a label ('sjis' → 'shift_jis'), or null when the label is unknown.
Decode
ValueTask<string?> Decode(byte[] bytes, string label = &quot;utf-8&quot;, bool fatal = false, bool ignoreBom = false)
Decodes bytes written in that encoding. Null when the label is unknown, or - with fatal - when the bytes don't fit the encoding.
Encode
ValueTask<byte[]> Encode(string text)
Encodes text as UTF-8, the only encoding TextEncoder produces.
GetUtf8ByteLength
ValueTask<int> GetUtf8ByteLength(string text)
How many bytes the text occupies as UTF-8, without moving the bytes across the boundary.
CreateDecoder
ValueTask<TextDecoderHandle?> CreateDecoder(string label = &quot;utf-8&quot;, bool fatal = false, bool ignoreBom = false)
Opens a streaming decoder for chunked content. Null when the label is unknown. Dispose it when the stream ends.
DisposeAsync
ValueTask DisposeAsync()
On scope/circuit teardown, drops any streaming decoders whose handle was never disposed.
TextDecoderHandle.Decode
ValueTask<string?> Decode(byte[] bytes, bool more = true)
Decodes one chunk. Pass more: false for the last one so a trailing partial character is flushed.
TextDecoderHandle.Flush
ValueTask<string?> Flush()
Ends the stream, emitting whatever partial character was pending.
TextDecoderHandle.DisposeAsync
ValueTask DisposeAsync()
Drops the decoder. Calling it again does nothing.
An unhandled error has occurred. Reload 🗙