C#で漢字をひらがなに変換する

2021/08/11

C#で漢字をひらがなに変換する方法を探していたのですが、IMEを使う方法だったり、Excelの機能を使う方法だったり、私の用途では使えない方法が検索に出てきて、方法を把握するのに少し時間がかかったので、メモしておきます。

結論としては、下記のページに記載の方法がシンプル、かつ、追加で nuget パッケージのインストールも不要だったので採用しました。

https://www.pine4.net/Memo/Article/Archives/424

インスタンス不要のユーティリティーとして以下のメソッドを書きました。

public static class TextUtility
{
    // IFELanguage2 Interface ID
    //[Guid("21164102-C24A-11d1-851A-00C04FCC6B14")]
    [ComImport]
    [Guid("019F7152-E6DB-11d0-83C3-00C04FDDB82E")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IFELanguage
    {
        int Open();
        int Close();
        int GetJMorphResult(uint dwRequest, uint dwCMode, int cwchInput, [MarshalAs(UnmanagedType.LPWStr)] string pwchInput, IntPtr pfCInfo, out object ppResult);
        int GetConversionModeCaps(ref uint pdwCaps);
        int GetPhonetic([MarshalAs(UnmanagedType.BStr)] string @string, int start, int length, [MarshalAs(UnmanagedType.BStr)] out string result);
        int GetConversion([MarshalAs(UnmanagedType.BStr)] string @string, int start, int length, [MarshalAs(UnmanagedType.BStr)] out string result);
    }

    public static string ToHiragana(string source)
    {
        IFELanguage? ifelang = null;
        try
        {
            var type = Type.GetTypeFromProgID("MSIME.Japan") ?? throw new Exception();
            ifelang = Activator.CreateInstance(type) as IFELanguage ?? throw new Exception();
            int hr = ifelang.Open();
            if (hr != 0)
            {
                throw Marshal.GetExceptionForHR(hr) ?? throw new Exception();
            }
            string yomigana;
            hr = ifelang.GetPhonetic(source, 1, -1, out yomigana);
            if (hr != 0)
            {
                throw Marshal.GetExceptionForHR(hr) ?? throw new Exception();
            }
            return yomigana;
        }
        finally
        {
            ifelang?.Close();
        }
    }
}

使用例

var result = TextUtility.ToHiragana("私は漢字をひらがなに変換しています");
Console.WriteLine(result);
// 出力: わたしはかんじをひらがなにへんかんしています

IFELanguage の初期化と破棄を変換の度に行いたくない場合のために、以下のようなクラスも作りました。(使った感じだと毎回初期化と破棄を行っても体感に違いはありませんでしたが一応)

public class TextConverter : IDisposable
{
    // IFELanguage2 Interface ID
    //[Guid("21164102-C24A-11d1-851A-00C04FCC6B14")]
    [ComImport]
    [Guid("019F7152-E6DB-11d0-83C3-00C04FDDB82E")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IFELanguage
    {
        int Open();
        int Close();
        int GetJMorphResult(uint dwRequest, uint dwCMode, int cwchInput, [MarshalAs(UnmanagedType.LPWStr)] string pwchInput, IntPtr pfCInfo, out object ppResult);
        int GetConversionModeCaps(ref uint pdwCaps);
        int GetPhonetic([MarshalAs(UnmanagedType.BStr)] string @string, int start, int length, [MarshalAs(UnmanagedType.BStr)] out string result);
        int GetConversion([MarshalAs(UnmanagedType.BStr)] string @string, int start, int length, [MarshalAs(UnmanagedType.BStr)] out string result);
    }

    private IFELanguage _ifelang;

    public TextConverter()
    {
        var type = Type.GetTypeFromProgID("MSIME.Japan") ?? throw new Exception();
        _ifelang = Activator.CreateInstance(type) as IFELanguage ?? throw new Exception();
        int hr = _ifelang.Open();
        if (hr != 0)
        {
            throw Marshal.GetExceptionForHR(hr) ?? throw new Exception($"{hr} is not error");
        }
    }

    public void Dispose()
    {
        _ifelang?.Close();
    }

    public string ToHiragana(string source)
    {
        int hr = _ifelang.GetPhonetic(source, 1, -1, out string yomigana);
        if (hr != 0)
        {
            throw Marshal.GetExceptionForHR(hr) ?? throw new Exception($"{hr} is not error");
        }
        return yomigana;
    }
}

使用例

var converter = new TextConverter();
var result = converter.ToHiragana("私は漢字をひらがなに変換しています。");
// 出力: わたしはかんじをひらがなにへんかんしています

  このエントリーをはてなブックマークに追加  

<<「ソフトウェア開発」の記事一覧に戻る

関連記事