いまUTF8のHTMLをTMemoに表示するためにUtf8ToAnsiを
使っているのですが、バイトコードC2A0(UTF8の半角空白)が
全部「?」になってしまいます。
テキストを保存したところ、コードは3Fでした。
現在は変換後の文字列に
AnsiReplaceText(s.Text, #63, ' ');
として半角空白に再変換をしています。
これを変換時に回避することはできますでしょうか?
よろしくお願いいたします。
=====================================
from: Takefumi-O
mail-address: takef...@gracix.com
url: http://www.gracix.com/
=====================================
--
高橋智宏
単純に コードポイント 0x000000a0 に対する CP932 への変換が
定義されていないのだと思います。
手元の MS-IME(WIndows XP SP3) の IME パッドでも
0x000000a0 の CP932 のコードは未定義になっています。
事前に C2A0 を 20 に変換するしかない気がします。
#つまり Windows の問題。
#CP932 には 0x00a0 は有るのにな~
Takefumi-o さんは書きました:
----------
東京都 日野市 中村拓男
> いまUTF8のHTMLをTMemoに表示するためにUtf8ToAnsiを
> 使っているのですが、バイトコードC2A0(UTF8の半角空白)が
> 全部「?」になってしまいます。
>
> テキストを保存したところ、コードは3Fでした。
>
> 現在は変換後の文字列に
> AnsiReplaceText(s.Text, #63, ' ');
> として半角空白に再変換をしています。
>
>
> これを変換時に回避することはできますでしょうか?
C2A0 とはノーブレークスペース(HTML表記で )だそうで、
半角空白とは若干意味が異なるようです。
ソースを見たところ、Utf8ToAnsi() の実装は
MultiByteToWideChar() による UTF-8 --> Unicode 変換
WideCharToMultiByte() による Unicode --> SJIS 変換
の2段階で変換してます。
前段は成功するのですが(U+00A0 に変換される)、後段が失敗してます。
後段でデフォルト文字が指定されていないため、デフォルト文字の
システムデフォルト?である '?' に変換されるようです。
Utf8ToAnsi() の同等関数を自作してデフォルト文字を与えれば
回避はできますが、手間の割にあまり意味が無さそうですので、
いまのままか、いっそソース側を成形してはどうかと思います。
--
松島
高橋(智)様、中村@ブレーン様、松島様お返事ありがとうございます。
環境はDelphi2007です。
変換はTStringListにHTMLを読み込み、
SL.Text := Utf8ToAnsi(SL.Text);
Memo1.Lines.Text := SL.Text;
として読み込みました。
そしてファイルを保存し、秀丸で開いたところ謎の??が大量に
出ていることに気がつきました。
> 事前に C2A0 を 20 に変換するしかない気がします。
> #つまり Windows の問題。
> #CP932 には 0x00a0 は有るのにな~
なるほど~
こういう風に調べられるのですね。
Windowsに原因があるとは思いもよりませんでした。
> C2A0 とはノーブレークスペース(HTML表記で )だそうで、
> 半角空白とは若干意味が異なるようです。
> ソースを見たところ、Utf8ToAnsi() の実装は
> MultiByteToWideChar() による UTF-8 --> Unicode 変換
> WideCharToMultiByte() による Unicode --> SJIS 変換
> の2段階で変換してます。
> 前段は成功するのですが(U+00A0 に変換される)、後段が失敗してます。
> 後段でデフォルト文字が指定されていないため、デフォルト文字の
> システムデフォルト?である '?' に変換されるようです。
が半角スペースとは違うのですね。
もう少し調べてみます。
DelphiはUniCodeを介して変換しているというのも初めてわかりました。
今回の問題は2段階で変換するしかないようですね。
HTMLが巨大になるとAnsiReplaceでは処理が戻ってこなくなって
しまうため、さらに工夫が必要だと感じました。
ありがとうございました。