TStreamReaderを利用してUTF-8(BOM付き)ファイルを読み込むと、Unicode 文字のマッピングがターゲットのマルチバイトコードページに存在しません」という例外が発生する

提供: Support
移動先: 案内検索

対象となるIDEのバージョン

  • Delphi/C++Builder/RAD Studio XE7〜10.2

問題

例えば、TStreamReaderを利用してDetectBOM=Trueを設定し、エンコード形式がUTF-8(BOM付き)のテキストファイルを読み込むと、

Unicode 文字のマッピングがターゲットのマルチバイトコードページに存在しません

という例外エラーが発生することがあります。


コード例は、以下の通りです。

..
var
  sr: TStreamReader;
  Path, str: String;
begin
  Path := ExtractFilePath(ParamStr(0)) + 'sample.txt'; //sample.txtの中身のテキストはUTF-8ファイル(BOM付き)

  sr := TStreamReader.Create(Path, TEncoding.Default, True);
  try
    while sr.Peek <> -1 do
    begin
      str := sr.ReadLine;
    end;
  finally
    FreeAndNil(sr);
  end;
end;

この例外エラーは、TStreamReader.FillBufferメソッドで発生しており、このメソッドは、以下の処理を行っています。


  1. ファイル(ストリーム)からバッファに読み込み
  2. 現在設定されているEncodingを使用して、マルチバイト文字を構成するコードが途中の場合はバッファ終端を縮める
  3. DetectBom=Trueであれば、バッファの先頭からBOMを読み込みEncodingを変更
  4. バッファの内容を、Encodingを使用して文字列に変換
  5. バッファの終端がマルチバイト文字を構成するコードが途中の場合は追加で読み込む


上記のTStreamReaderの使用コード例の場合は、2.の処理をTEncoding.Default、そして 4.の処理をTEncoding.Utf8で行っているため、バッファ境界の文字によって例外が発生することがあります。

解決

この問題は、Embarcadero Quality Portalへ報告済みで、10.3で修正済みです

ケース番号 タイトル
RSP-9569 TStreamReader Detect BOM does not use the proper encoding if the file has a bom, and a default encoding is passed to TStreamReader

(Embarcadero Quality Portalへのログインは、EDNアカウントが必要)


誠に恐れ入りますが、本件を解決するためにはDelphi/C++Builder/RAD Studio 10.3以降へアップデートしてください。