C# 外部ライブラリを使わずに半角→全角カタカナ変換

C#で半角カタカナを全角に変換する必要が出てきて、ネットで調べてみたらVB.NETの関数や他のライブラリを使って変換する方法が多いようです。
なんとなくしたくないから、試行錯誤しながらなんとかできるようになりました。

TL;DR

簡単に言えば、半角と全角の辞書を作って正規表現でマッチするだけですが、正規表現を使うときに罠があって試行錯誤しました。
辞書を作るといえば、力仕事のように聞こえますが、Excelで簡単に作れますし、一回作っておけばずっと使えるから別に手間だと思いませんでした。

目次

半角→全角カタカナの辞書を作る

Excelで辞書の本体を簡単に作る

Excelで全角のだけ入力して、その他は全部数式で自動生成します。

ExcelでDictionaryのコードを生成

   こんな感じになります:

ExcelでDictionaryのコードを生成結果



ExcelからC#ソースにコピペして辞書完成

長いので折りたたんでおきます。

コードはこちらです。
Dictionary<string,string> dictKatakana = new Dictionary<string, string> () { {"ア","ア"}, {"ィ","ィ"}, {"イ","イ"}, {"ゥ","ゥ"}, {"ウ","ウ"}, {"ェ","ェ"}, {"エ","エ"}, {"ォ","ォ"}, {"オ","オ"}, {"カ","カ"}, {"ガ","ガ"}, {"キ","キ"}, {"ギ","ギ"}, {"ク","ク"}, {"グ","グ"}, {"ケ","ケ"}, {"ゲ","ゲ"}, {"コ","コ"}, {"ゴ","ゴ"}, {"サ","サ"}, {"ザ","ザ"}, {"シ","シ"}, {"ジ","ジ"}, {"ス","ス"}, {"ズ","ズ"}, {"セ","セ"}, {"ゼ","ゼ"}, {"ソ","ソ"}, {"ゾ","ゾ"}, {"タ","タ"}, {"ダ","ダ"}, {"チ","チ"}, {"ヂ","ヂ"}, {"ッ","ッ"}, {"ツ","ツ"}, {"ヅ","ヅ"}, {"テ","テ"}, {"デ","デ"}, {"ト","ト"}, {"ド","ド"}, {"ナ","ナ"}, {"ニ","ニ"}, {"ヌ","ヌ"}, {"ネ","ネ"}, {"ノ","ノ"}, {"ハ","ハ"}, {"バ","バ"}, {"パ","パ"}, {"ヒ","ヒ"}, {"ビ","ビ"}, {"ピ","ピ"}, {"フ","フ"}, {"ブ","ブ"}, {"プ","プ"}, {"ヘ","ヘ"}, {"ベ","ベ"}, {"ペ","ペ"}, {"ホ","ホ"}, {"ボ","ボ"}, {"ポ","ポ"}, {"マ","マ"}, {"ミ","ミ"}, {"ム","ム"}, {"メ","メ"}, {"モ","モ"}, {"ャ","ャ"}, {"ヤ","ヤ"}, {"ュ","ュ"}, {"ユ","ユ"}, {"ョ","ョ"}, {"ヨ","ヨ"}, {"ラ","ラ"}, {"リ","リ"}, {"ル","ル"}, {"レ","レ"}, {"ロ","ロ"}, {"ヮ","ヮ"}, {"ワ","ワ"}, {"ヰ","ヰ"}, {"ヱ","ヱ"}, {"ヲ","ヲ"}, {"ン","ン"}, {"ヴ","ヴ"}, {"ヵ","ヵ"}, {"ヶ","ヶ"}, {"ー","ー"} };

変換関数を作る

試行錯誤

!注意:このセクションに間違ったコードがあります!

public string HalfToFullKatakana(string input) {//このコードは間違っています。使用しないでください。 Regex re = new Regex(@"[\uFF61-\uFF9F]"); //半角カタカナを表す正規表現 string output = re.Replace(input, match => {//Matchした場合の処理 if (dictKatakana.ContainsKey(match.Value)) {//辞書にあれば辞書にある値を返す return dictKatakana[match.Value]; } else {//辞書になければつまり半角カタカナでなければ変換せずに返す return match.Value; } }); return output; }

一見問題がなさそうですが、実施に変換してみます。

string half = "パソコン机にキーボードがある"; string full=HalfToFullKatakana(half); Console.WriteLine(half); Console.WriteLine(full);

出力結果は以下です:

パソコン机にキーボードがある パソコン机にキーボードがある

パ ボ ドの濁点が少し離れている・・・でも私は当時気づきませんでした(笑)。
変換された文字が検索機能に使われたので、検索しても当たらないからはじめて気づきました。
半角カタカナの濁点は別文字になっているから、正規表現で一部しかマッチしていないからこうなったと分かりました。例えば、
パで出来ています。正規表現で辞書を引いたときは、がマッチされて、全角のが返されますが、濁点はマッチされないので、そのまま返されるので、パという変な組み合わせになってしまいます。

間違いを修正して完成

public string HalfToFullKatakana(string input) {//これは修正されたバージョンです。 Regex re = new Regex(@"[ヲ-ン]゙|[ヲ-ン]゚|[ヲ-ン]");   //↑ここだけ修正 string output = re.Replace(input, match => {//Matchした場合の処理 if (dictKatakana.ContainsKey(match.Value)) {//辞書にあれば辞書にある値を返す return dictKatakana[match.Value]; } else {//辞書になければつまり半角カタカナでなければ変換せずに返す return match.Value; } }); return output; }

修正したのは一カ所だけです:

Regex re = new Regex(@"[ヲ-ン]゙|[ヲ-ン]゚|[ヲ-ン]");

正規表現のパターンを変えました。この3種類の順番が重要です。
濁点のついている半角カタカナを先にマッチさせればいいです。
修正後の結果出力:

パソコン机にキーボードがある パソコン机にキーボードがある

濁点は元に戻りました~ この方法は意外とシンプルすぎて大丈夫かなと少し不安でしたが、数ヶ月使ってきて、今のところ問題がなさそうです。
何か思い及ばないところでバグるかもしれないので、留意しながら使っていきたいと思います。

コメント

このブログの人気の投稿

C# WebView2.ExecuteScriptAsync()のいくつかの使い方とDebug方法

C# WebView2を通じてWebサーバーなしでJavaScriptからローカルファイルを読み書き