TStreamReaderを利用してUTF-8(BOM付き)ファイルを読み込むと、Unicode 文字のマッピングがターゲットのマルチバイトコードページに存在しません」という例外が発生する
対象となる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メソッドで発生しており、このメソッドは、以下の処理を行っています。
- ファイル(ストリーム)からバッファに読み込み
- 現在設定されているEncodingを使用して、マルチバイト文字を構成するコードが途中の場合はバッファ終端を縮める
- DetectBom=Trueであれば、バッファの先頭からBOMを読み込みEncodingを変更
- バッファの内容を、Encodingを使用して文字列に変換
- バッファの終端がマルチバイト文字を構成するコードが途中の場合は追加で読み込む
上記の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以降へアップデートしてください。