tacamy--blog

JavaScriptを勉強中の人のブログです。

JavaScriptで文字列をShift_JISに変換&URLエンコードする

ユーザーが入力した文字列を元にして、そのキーワードの検索結果ページへリンクしたいけど、そのキーワードをJavaScriptShift_JISエンコードしないといけないという仕様を実装した。JavaScript文字コードを変換するというのをしたことがなくて調べたので、忘れないうちにメモ。

文字コードUnicodeからShift_JISに変換

JavaScriptの世界の文字コードUnicodeなので、まずは、入力されたキーワードをShift_JISに変換する必要がある。

npmにencoding-japaneseというライブラリがあったので、利用することに。

www.npmjs.com

ちなみに、文字コードの変換だけだと iconv-lite - npm の方が有名っぽい雰囲気だったけど、encoding-japaneseはURLエンコードもできるからそっちにした。

JavaScriptでの文字コード変換のことをまったく理解していなくて、最初は文字列をそのまま渡せばいいのかと思ってたけど、文字列を1文字ずつ分解して、文字コードの数値の配列に変換しないといけないっぽい。ぐぐってると「コードユニット値」とか「コードセットの値」とかいろんな言葉の定義が出てきてよくわからなかったけど、とりあえず数値の配列にする。

JavaScript標準の.charCodeAt(i)メソッドで文字コードの数値を取れるから、文字列の長さ分ループしてindexを指定したらできた。

developer.mozilla.org

import encoding from 'encoding-japanese';

const keyword = 'キーワード';

// キーワードを文字コードの数値の配列に変換
const unicodeArray = [];
for (let i = 0; i < keyword.length; i++) {
  unicodeArray.push(keyword.charCodeAt(i));
}

これで文字コード変換の準備ができたので、encoding-japaneseのconvert()を使ってShift_JISに変換する。

// Shift_JISに変換
const sjisArray = encoding.convert(unicodeArray, {
  to: 'SJIS',
  from: 'UNICODE',
});

Shift_JIS文字コードの配列をURLエンコード

encoding-japaneseのurlEncode()でURLエンコードができるので、先ほど生成したShift_JIS文字コードの配列を引数に渡して、URLエンコードした文字列を生成する。

// SJISのキーワードをURLエンコード
const encodedKeyword = encoding.urlEncode(sjisArray);

あとは、テンプレートリテラルなりなんなりで、検索結果ページのURLを組み立てて完成!

// リンク先のURLを生成
const href = `https://www.example.com/search?keyword=${encodedKeyword}`;

まとめ

全部のコードを合わせるとこうなる。

import encoding from 'encoding-japanese';

const keyword = 'キーワード';

// キーワードを文字コードの数値の配列に変換
const unicodeArray = [];
for (let i = 0; i < keyword.length; i++) {
  unicodeArray.push(keyword.charCodeAt(i));
}

// Shift_JISに変換
const sjisArray = encoding.convert(unicodeArray, {
  to: 'SJIS',
  from: 'UNICODE',
});

// SJISのキーワードをURLエンコード
const encodedKeyword = encoding.urlEncode(sjisArray);

// リンク先のURLを生成
const href = `https://www.example.com/search?keyword=${encodedKeyword}`;

便利なライブラリがあるというのに、文字コードの概念がよくわからなくて使い方が分からず、結構悩んでしまった。

最初の方、文字列そのまま渡しても変換できず、ドキュメント読んだらArrayを渡すとか書いてあるけど、なんの配列なんだろって思って、文字列を一文字ずつ分解した配列とか渡してた😅

あと、UnicodeUTF-16の違いもよくわかってないままだ。