Delphi XE5でNKF32.DLLを使ってひらがなをカタカナに変換する

Delphi XE5でNKF32.DLLを使って、ひらがなをカタカナに変換するアプリケーションの例です。
Googleで検索しても古い例ばかり見つかるので、最近のバージョンで使える方法を紹介します。

002

あらかじめ「nkf.exe nkf32.dll Windows用」をダウンロードして、NKF32.DLLをパスの通ったフォルダー、または実行ファイルと同じフォルダーに配置します。

フォームにTButtonを1つ、TEditを2つ配置します。

001

ボタンをクリックするとKatakana関数を呼び出して、Edit1に入力された文字をカタカナに変換して、Edit2に表示します。

procedure TForm1.Button1Click(Sender: TObject);
begin
  Edit2.Text := Katakana(Edit1.Text);
end;

では、Katakana関数を見ていきます。

function TForm1.Katakana(const S: string): string;
const
  // DLLのファイル名
  LIB_NAME = 'NKF32.DLL';
  // NKFのオプション文字列
  Option = '-Wwx --katakana';
begin
end;

定数「Option」はNKFのオプションです。
UTF-8のバイト列を受け取り、カタカナに変換して、UTF-8のバイト列を返す設定です。

NKFのオプションには次のようなものがあります。

入力文字のオプション

  • -J
    ISO-2022-JP を仮定する。
  • -E
    日本語 EUCを仮定する。
  • -S
    Shift_JIS を仮定する。
  • -W
    UTF-8 を仮定する。

出力文字のオプション

  • -j
    JIS コードを出力する。
  • -e
    EUC コードを出力する。
  • -s
    Shift_JIS コードを出力する。
  • -w
    UTF8 コードを出力する。 (BOM 無し)

文字変換のオプション

  • –hiragana
    平仮名に変換する
  • –katakana
    片仮名に変換する
  • -X
    半角カナを全角カナへと変換する。
  • -Z
    全角英数字を半角に変換する。

次は、DLLを読み込む処理です。

var
  Handle: THandle;
begin
  // ライブラリをロードする
  Handle := SafeLoadLibrary(LIB_NAME);
  if Handle = 0 then
    raise Exception.Create('ライブラリのロードに失敗しました。');
  try
    …
  finally
    FreeLibrary(Handle);
  end;
end;

System.SysUtils.SafeLoadLibrary関数を使ってDLLをロードします。
処理が終わったらFreeLibrary関数でDLLを解放します。

DLLをロードしたら、次は関数のアドレスを取得します。

取得する関数の型を定義します。
今回はSetNkfOption関数とNkfConvertSafe関数を使用します。

type
  /// <summary>
  /// 変換オプション文字列を指定します。連続したオプションの指定も可能です。
  /// </summary>
  /// <param name="optStr">
  /// 変換オプション文字列を指定します。
  /// </param>
  /// <returns>
  /// 関数が成功すると 0 が返ります。関数が失敗すると負値が返ります。
  /// </returns>
  TSetNkfOption = function(optStr: PAnsiChar): Integer; stdcall;

  /// <summary>
  /// 文字コードを変換します。
  /// </summary>
  /// <param name="outStr">
  /// 出力文字列を返します。
  /// </param>
  /// <param name="nOutBufferLength">
  /// outStrの領域長をバイト数で与えます。
  /// </param>
  /// <param name="lpBytesReturned">
  /// 出力文字列の長さ(出力文字列の後ろに付加される0を含まない)をバイト数で返します。
  /// </param>
  /// <param name="inStr">
  /// 入力文字列を与えます。
  /// </param>
  /// <param name="nInBufferLength">
  /// 入力文字列の長さをバイト数で与えます。
  /// </param>
  TNkfConvertSafe = function(outStr: PAnsiChar; nOutBufferLength: DWORD;
    var lpBytesReturned: DWORD; inStr: PAnsiChar; nInBufferLength: DWORD)
    : BOOL; stdcall;

関数のアドレスを格納する変数を宣言します。

var
  SetNkfOption: TSetNkfOption;
  NkfConvertSafe: TNkfConvertSafe;

GetProcAddress関数を使って、関数のアドレスを取得します。

// 関数のアドレスを取得する
@SetNkfOption := GetProcAddress(Handle, 'SetNkfOption');
if @SetNkfOption = nil then
  raise Exception.Create('SetNkfOption関数の取得に失敗しました。');

@NkfConvertSafe := GetProcAddress(Handle, 'NkfConvertSafe');
if @NkfConvertSafe = nil then
  raise Exception.Create('NkfConvertSafe関数の取得に失敗しました。');

変換する文字列のUTF-8のバイト列を取得します。
UTF-8に変換するのは、NKF32.DLLに受け渡しする文字列の文字コードをNKFのオプションでUTF-8に指定しているためです。

var
  InBytes: TBytes;

// 変換する文字列のUTF8のバイト列
InBytes := TEncoding.UTF8.GetBytes(S);

変換した文字列の長さを取得します。
長さを格納する変数を定義します。

var
  BytesReturned: DWORD;

SetNkfOption関数でオプションを設定して、NkfConvertSafe関数で変換します。
このとき、NkfConvertSafeから出力文字列を受け取らず、変換した文字列の長さだけ受け取ります。

// 出力文字列の長さを取得する
if SetNkfOption(Option) < 0 then
  raise Exception.Create('SetNkfOption関数の呼び出しに失敗しました。');

if not NkfConvertSafe(nil, 0, BytesReturned, PAnsiChar(InBytes),
  Length(InBytes)) then
  raise Exception.Create('NkfConvertSafe関数の呼び出しに失敗しました。');

変換したバイト列を受け取る変数を定義します。

var
  OutBytes: TBytes;

変換結果の長さを設定します。

SetLength(OutBytes, BytesReturned);

変換します。
今度はNkfConvertSafeから出力文字列を受け取ります。

// 文字列を変換する
if SetNkfOption(Option) < 0 then
  raise Exception.Create('SetNkfOption関数の呼び出しに失敗しました。');

if not NkfConvertSafe(PAnsiChar(OutBytes), Length(OutBytes), BytesReturned,
  PAnsiChar(InBytes), Length(InBytes)) then
  raise Exception.Create('NkfConvertSafe関数の呼び出しに失敗しました。');

受け取ったバイト配列はUTF-8の文字列です。
ユニコード文字列に変換します。

// UTF8のバイト列をユニコード文字列に変換する
Result := TEncoding.UTF8.GetString(OutBytes);

アプリケーションを実行します。

Edit1に変換する文字列を入力してボタンを押すと、Edit2に変換した文字が表示されます。

002

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください