13

ファイルに有効な UTF-8 BOM があるが、無効な UTF8 エンコーディングが含まれていて、Delphi (2009+) エンコーディング対応メソッドのいずれかによって読み取られる場合LoadFromFile、結果はエラー表示のない完全に空のファイル。私のアプリケーションのいくつかでは、この場合もエラー レポートが得られなくても、いくつかの不正なエンコーディングを単純に失うことを好みます。

デバッグにより、 が 2 回呼び出されていることがわかりMultiByteToWideCharます。最初に出力バッファー サイズを取得し、次に変換を行います。FMBToWCharFlagsただし、TEncoding.UTF8 にはこれらの呼び出しのプライベート値が含まれており、これはMB_ERR_INVALID_CHARS値で初期化されます。そのため、charcount を取得する呼び出しは 0 を返し、ロードされたファイルは完全に空になります。フラグなしでこの API を呼び出すと、「不正なコード ポイントが黙ってドロップされます」。

私の質問は、これがプライベートな値であるという事実を回避するために、エンコーディング領域のクラスのネストをどのように織り込むのが最善かということです (すべてのスレッドのクラス var であるため、そうする必要があります)。Marco Cantu の Delphi 2009 book のガイダンスを使用して、カスタム UTF8 エンコーディングを追加できると思います。MultiByteToWideCharまた、フラグなしで再度呼び出した後、エンコーディング エラーが返された場合は、オプションで例外を発生させることができます。しかし、それは私のカスタムエンコーディングを の代わりに使用する方法の問題を解決しませんTencoding.UTF8

初期化時にこれをアプリケーションのデフォルトとして設定できれば、おそらくクラス var for を実際に変更して、Tencoding.UFT8おそらくこれで十分でしょう。

もちろん、より堅牢な設計を要求する QC レポートを提出するのを待たずに解決策が必要であり、それが受け入れられ、変更が加えられることはありません。

どんなアイデアでも大歓迎です。また、これがまだインストールしていない XE4 の問題であることを確認できますか?

4

4 に答える 4

12

MB_ERR_INVALID_CHARSをサポートするように Indy を最初に更新したときにこの問題に遭遇し、を指定しないように UTF-8 処理用TEncodingのカスタム派生クラスを実装することになりました。クラスヘルパーを使うとは思いもしませんでした。TEncodingMB_ERR_INVALID_CHARS

ただし、この問題は UTF-8 に限ったことではありません。いずれかのTEncodingクラスのデコードに失敗すると、例外が発生するのではなく、空白の結果になります。ほとんどの RTL/VCL が代わりに例外を使用しているのに、Embarcadero がそのルートを選択した理由は、私には理解できません。エラー時に例外を発生させないことで、回避しなければならないかなりの量の問題が Indy で発生しました。

于 2013-05-14T01:41:37.603 に答える
3

これは、少なくとも Delphi XE5 では非常に簡単に実行できます (以前のバージョンはチェックしていません)。独自のインスタンスを作成するだけTUTF8Encodingです:

procedure LoadInvalidUTF8File(const Filename: string);
var
  FEncoding: TUTF8Encoding;
begin
  FEncoding := TUTF8Encoding.Create(CP_UTF8, 0, 0); 
                      // Instead of CP_UTF8, MB_ERR_INVALID_CHARS, 0
  try
    with TStringList.Create do
    try
      LoadFromFile(Filename, FEncoding);
      // ...
    finally
      Free;
    end;
  finally
    FEncoding.Free;
  end;
end;

ここでの唯一の問題はIsSingleByte、新しくインスタンス化された のプロパティがTUTF8Encoding誤って に設定されることFalseですが、このプロパティは現在、Delphi ソースのどこにも使用されていません。

于 2014-07-29T04:46:50.413 に答える