Universal Character Set Detector C LibraryをDelphi XEから使用する
C++Builderで試した、Mozillaのエンコーディング自動判別ライブラリである「universalchardet」をDLL化したのをDelphiで動作させてみました。バイナリはhttp://a7m.sakura.ne.jp/SOURCE/universalchardet-CB.7zに用意したもので、C++Builder XE(BCC32.EXE 6.31)でコンパイル。
Delphiでuniversalchardet.dllを使うためには、DLLの宣言を記述したユニットを作成しなければならない。
unit universalchardet; interface type chardet_t = Pointer; const CHARDET_RESULT_OK = 0; CHARDET_RESULT_NOMEMORY = -1; CHARDET_RESULT_INVALID_DETECTOR = -2; CHARDET_MAX_ENCODING_NAME = 64; CHARDET_ENCODING_ISO_2022_JP = 'ISO-2022-JP'; CHARDET_ENCODING_ISO_2022_CN = 'ISO-2022-CN'; CHARDET_ENCODING_ISO_2022_KR = 'ISO-2022-KR'; CHARDET_ENCODING_ISO_8859_5 = 'ISO-8859-5'; CHARDET_ENCODING_ISO_8859_7 = 'ISO-8859-7'; CHARDET_ENCODING_ISO_8859_8 = 'ISO-8859-8'; CHARDET_ENCODING_BIG5 = 'BIG5'; CHARDET_ENCODING_GB18030 = 'GB18030'; CHARDET_ENCODING_EUC_JP = 'EUC-JP'; CHARDET_ENCODING_EUC_KR = 'EUC-KR'; CHARDET_ENCODING_EUC_TW = 'EUC-TW'; CHARDET_ENCODING_SHIFT_JIS = 'SHIFT_JIS'; CHARDET_ENCODING_IBM855 = 'IBM855'; CHARDET_ENCODING_IBM866 = 'IBM866'; CHARDET_ENCODING_KOI8_R = 'KOI8-R'; CHARDET_ENCODING_MACCYRILLIC = 'MACCYRILLIC'; CHARDET_ENCODING_WINDOWS_1251 = 'WINDOWS-1251'; CHARDET_ENCODING_WINDOWS_1252 = 'WINDOWS-1252'; CHARDET_ENCODING_WINDOWS_1253 = 'WINDOWS-1253'; CHARDET_ENCODING_WINDOWS_1255 = 'WINDOWS-1255'; CHARDET_ENCODING_UTF_8 = 'UTF-8'; CHARDET_ENCODING_UTF_16BE = 'UTF-16BE'; CHARDET_ENCODING_UTF_16LE = 'UTF-16LE'; CHARDET_ENCODING_UTF_32BE = 'UTF-32BE'; CHARDET_ENCODING_UTF_32LE = 'UTF-32LE'; CHARDET_ENCODING_HZ_GB_2312 = 'HZ-GB-2312'; CHARDET_ENCODING_X_ISO_10646_UCS_4_3412 = 'X-ISO-10646-UCS-4-3412'; CHARDET_ENCODING_X_ISO_10646_UCS_4_2143 = 'X-ISO-10646-UCS-4-2143'; // Unused CHARDET_ENCODING_ISO_8859_2 = 'ISO-8859-2'; CHARDET_ENCODING_WINDOWS_1250 = 'WINDOWS-1250'; CHARDET_ENCODING_TIS_620 = 'TIS-620'; function chardet_create(var pdet: chardet_t): integer; stdcall; external 'universalchardet.dll' name '_chardet_create'; procedure chardet_destroy(det: chardet_t); stdcall; external 'universalchardet.dll' name '_chardet_destroy'; function chardet_handle_data(det: chardet_t; const data: PAnsiChar; len: Cardinal): integer; stdcall; external 'universalchardet.dll' name '_chardet_handle_data'; function chardet_data_end(det: chardet_t): integer; stdcall; external 'universalchardet.dll' name '_chardet_data_end'; function chardet_reset(det: chardet_t): integer; stdcall; external 'universalchardet.dll' name '_chardet_reset'; function chardet_get_charset(det: chardet_t; namebuf: PAnsiChar; buflen: Cardinal): integer; stdcall; external 'universalchardet.dll' name '_chardet_get_charset'; implementation end.
このファイルをuniversalchardet.pasとして保存する。
実際に使用する場合は、users節にuniversalchardetを追加する。サンプルコードは以下の通り。
procedure TForm1.Button1Click(Sender: TObject); var ms: TMemoryStream; enc: TEncoding; encname: array[0..CHARDET_MAX_ENCODING_NAME] of AnsiChar; det: chardet_t; res: Integer; begin ms := TMemoryStream.Create; // ファイルのロード ms.LoadFromFile(filename); // オフセットをストリームの先頭に ms.Position := 0; // エンコーディングの判別をする det := nil; chardet_create(det); res := chardet_handle_data(det, ms.Memory, ms.Size); chardet_data_end(det); // エンコーディング名の取得 chardet_get_charset(det, encname, CHARDET_MAX_ENCODING_NAME); chardet_destroy(det); // 自動判別結果を元にエンコーディングを判別して読み込み enc := nil; try enc := TEncoding.GetEncoding(encname); except on EEncodingError do enc := TEncoding.Default; end; Memo1.Lines.LoadFromStream(ms, enc); ms.Free; end;