QiitaでTextDecoder
を使ってShift-JISコードを取得する記事(McbeEringi氏)を見かけました。記事中のコードは理解できていないのですが、発想を参考にShift-JISコード配列を取得するクラスを作成しました。
// UnicodeコードポイントからShift-JISへの変換機能を提供します。 // 初期化時に重い処理があります。できる限り使いまわしてください。 class SjisEncoder { #sjisToCodePoint; // Uint32Array constructor() { const sjisDecoder = new TextDecoder("sjis"); const maxSjis = 0xffff; this.#sjisToCodePoint = new Uint32Array(maxSjis); const buffer = new Uint16Array(1); for (let i = 0; i < this.#sjisToCodePoint.length; i++) { buffer[0] = i; this.#sjisToCodePoint[i] = sjisDecoder.decode(buffer).codePointAt(0); } } // コードポイントからShift-JISコードの配列を取得します。 // 変換できない文字が含まれる場合はRangeError例外を送出します。 codePointToSjiCodes(codepoint) { const i = this.#sjisToCodePoint.indexOf(codepoint); if (i == -1) throw new RangeError("コードポイントに対応するShift-JIS文字がありません。"); // 16ビットLE→8ビット×1or2に変換 if (i <= 0xff) return [i]; else return [i & 0xff, (i >> 8) & 0xff]; } // 文字列からShift-JISコードの配列を取得します。 // 変換できない文字が含まれる場合はRangeError例外を送出します。 encode(s) { const codepoints = Array.from(s, ch => ch.codePointAt(0)); return codepoints.flatMap(codepoint => sjisChars.codePointToSjiCodes(codepoint)); } }
使用例です。
const sjisChars = new SjisEncoder(); console.log(sjisChars.encode("0123abcあいう亜位鵜㈱㍻")); console.log(sjisChars.encode("🍊")); // 例外が発生します。
JavaScript動向を追えていないので古い書き方かもしれないことには注意してください。