[Delphi:91040] Utf8ToAnsiで文字がC2A0が?になる

1,076 views
Skip to first unread message

Takefumi-o

unread,
Jan 22, 2009, 12:04:53 AM1/22/09
to Del...@ml.users.gr.jp
皆様こんにちは。


いまUTF8のHTMLをTMemoに表示するためにUtf8ToAnsiを
使っているのですが、バイトコードC2A0(UTF8の半角空白)が
全部「?」になってしまいます。

テキストを保存したところ、コードは3Fでした。

現在は変換後の文字列に
 AnsiReplaceText(s.Text, #63, ' ');
として半角空白に再変換をしています。


これを変換時に回避することはできますでしょうか?


よろしくお願いいたします。

=====================================

from: Takefumi-O
mail-address: takef...@gracix.com
url: http://www.gracix.com/

=====================================

TAKAHASHI, Tomohiro

unread,
Jan 23, 2009, 12:20:50 AM1/23/09
to Del...@ml.users.gr.jp
高橋(智)です。
確認させてください。使用されているDelphiのバージョンは何でしょうか?
HTMLファイル(orデータ)の読み込み処理も含め、どのようなコード書かれているのでしょうか?
コード全体を掲載されたほうが、みなさんの理解の助けになると思います。

--
高橋智宏

中村拓男

unread,
Jan 23, 2009, 3:11:40 AM1/23/09
to Del...@ml.users.gr.jp
中村@ブレーンです。

単純に コードポイント 0x000000a0 に対する CP932 への変換が
定義されていないのだと思います。

手元の MS-IME(WIndows XP SP3) の IME パッドでも
0x000000a0 の CP932 のコードは未定義になっています。
事前に C2A0 を 20 に変換するしかない気がします。

#つまり Windows の問題。
#CP932 には 0x00a0 は有るのにな~

Takefumi-o さんは書きました:

----------
東京都 日野市 中村拓男

H.Matsushima

unread,
Jan 23, 2009, 3:33:27 AM1/23/09
to Del...@ml.users.gr.jp
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() の同等関数を自作してデフォルト文字を与えれば
回避はできますが、手間の割にあまり意味が無さそうですので、
いまのままか、いっそソース側を成形してはどうかと思います。

--
松島


Takefumi-o

unread,
Jan 24, 2009, 9:37:34 AM1/24/09
to Del...@ml.users.gr.jp
こんばんは。
お返事が遅くなりました。


高橋(智)様、中村@ブレーン様、松島様お返事ありがとうございます。

環境は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では処理が戻ってこなくなって
しまうため、さらに工夫が必要だと感じました。


ありがとうございました。

Reply all
Reply to author
Forward
0 new messages