いつもお世話になっております。
ちゃかです。
環境は以下の通りです。
・Windows Vista Bussiness
・Delphi 7 Professinal
・Oracle 10g
早速ですが、質問です。
以下のようにADOQueryを使用し、oracleに接続し、文字列を取得しようと思っています。
しかし、「〜」が「?」となって文字化けしてしまいます。
解決方法を探していたのですが、どうやらOracle の UNICODE のコードマッピングが原因なようです。
(引用元:http://www2.big.or.jp/~osamu/Delphi/delphi-browse.cgi?index=071738)
しかし、オラクルの設定をキャラセットを「Windows-31J」等に変更すれば解決するらしいのですが
環境を変えるのはこちらの都合で申し訳ないのですが不可能なのです(すいません・・・)。
ネット上にある文字列変換関数ユニットを使用してみたのですがどうもうまくいきません。
(SJIStoUTF,SJIStoUTFN,UTFtoSJIS,UTFNtoSJIS,JisToSJis,SJisToJis,HanToZen,
HanToZen2,UTFtoSJIS,UTFNtoSJIS,Utf8Decode,Utf8Encode等々・・・)
VBでは
VBのReplace関数を使用した「〜」文字化け対策の例】
strSHONIN_NAME = Replace("" & OraDynaset("SHONIN_NAME"), ChrW(12316), "〜", 1, -1, vbTextCompare)
と簡単に変換できるようなのですが、Delphiでは不可能なのでしょうか?
皆様のお力をお借りしたいです。
多くの方がこの問題にて躓いてるみたいなので既出だと思います。
自分の情報収集能力の無さに愕然としながら恥を忍んで質問させていただきました。
どうかよろしくお願い致します。
//-----------------------------------------
//以下ソース
//-----------------------------------------
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('select * from test');
ADOQuery1.Open;
while ADOQuery1.Eof = False do
begin
showmessage(ADOQuery1.FieldByName('text').AsString);
ADOQuery1.Next;
end;
ADOQuery1.Close;
結果:DB上「あいう」 →「あいう」
: 「え〜お」 →「え?お」
所謂"波ダッシュ(WAVE DASH)問題"ですね。
http://ja.wikipedia.org/wiki/%E6%B3%A2%E3%83%80%E3%83%83%E3%82%B7%E3%83%A5#Unicode.E3.81.AB.E9.96.A2.E9.80.A3.E3.81.99.E3.82.8B.E5.95.8F.E9.A1.8C
>Delphiでは不可能なのでしょうか?
Delphiでも2007とかだとAsWideStringが使えるので、
#$301C(波ダッシュ:WAVE DASH)と#$FF5E(全角チルダ:FULLWIDTH TILDE)を
変換(VBの例のように)するだけでいいと思われるのですが、
残念ながらDelphi7にはAsWideStringがありません。
試せる環境がないので推測ですが、
1.WideStringの変数(Wとする)を用意。
2.そこへAsVariantで取得した値を代入。
W := ADOQuery1.FieldByName('text').AsVariant;
3.#$301Cを#$FF5Eへ置換。
4.(Ansi)String型の変数(Aとする)へWideStringの変数を代入。
A := W;
これでうまくいくかもしれません。
DEKO様
いつもお世話になっております。
ちゃかです。
お返事ありがとうございます。
「〜」文字はうまく取れるようになりました。
しかし、「?」文字も「〜」に変換されてしまいました。
これは変換方法がまずいのでしょうか?
いろいろ考えてみたのですが以下の結果から
Oracleの「〜」と「?」は「#$301C」ということなのでしょうか・・?
「?」は「#$FF1F」だと思ったのですが・・・。
(*
引用元:http://ash.jp/code/unitbl21.htm
区 点 JIS SJIS EUC UTF-8 UTF-16 字
01 33 2141 8160 A1C1 E3809C 301C 〜
01 09 2129 8148 A1A9 EFBC9F FF1F ?
*)
理解できないことばかりでうまく説明できていませんが、
引き続き皆様よろしくお願い致します。
//-----------------------------------------
//以下ソース
//-----------------------------------------
var
WS : WideString;
AS : AnsiString;
begin
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('select * from test');
ADOQuery1.Open;
while ADOQuery1.Eof = False do
begin
WS := ADOQuery1.fieldByName('test').AsVariant;
AS := StringReplace(wk_WS,#$301C,#$FF5E,[rfReplaceAll]);
showmessage(ADOQuery1.FieldByName('text').AsString);
ADOQuery1.Next;
end;
ADOQuery1.Close;
end;
結果:DB上 ⇒ ShowMessage
・「あいう」⇒「あいう」
・「あ〜う」⇒「あ〜う」
・「あ?う」 ⇒「あ〜う」
・「? / 〜」⇒「〜 / 〜」
・「〜 / ?」⇒「〜 / 〜」
StringReplaceはWideStringに対応していません。
# WideStringを突っ込むと暗黙的にAnsi変換が行われて
# 処理されるので、すべての?が〜に変換されてしまいます。
WideStringをforで回すなりして自前で置換する必要があります。
var
i:Integer;
A: String;
WS: WideString;
begin
WS := (処理);
for i:=1 to Length(WS) do
if WS[i] = #$301C then
WS[i] := #$FF5E;
A := WS;
こんな感じです。
>Oracleの「〜」と「?」は「#$301C」ということなのでしょうか・・?
>「?」は「#$FF1F」だと思ったのですが・・・。
SHIFT-JISの"〜"は波ダッシュ(8160:#$301C)です。
しかし、Windowsはこれを全角チルダ(#$FF5E)に割り当てています。
UnicodeからSHIFT-JISへ変換しようとすると#$FF5Eに相当するJIS文字がないため、
変換できなかった文字の代替文字として設定されている"?(#$FF1F)"が表示されてしまうという事です。
横から失礼
環境はVistaみたいですし、
今回の場合は
WS:WideString;
WS := ADOQuery1.fieldByName('test').AsVariant;
showmessage(WS);
でいいと思います。
Oracle,WindowsのどちらでSHIFT-JIS変換するかの問題のように思えます。
あー失礼しました。
だめなんですね。
知らないことには顔を出してはいかんですな;;
すみません
Oracleに格納されているコードが(多分)波ダッシュ(8160:#$301C)なのです。
# Unicodeで格納されているのでしょう。
これをString(AsString)で取り出そうとすると、WindowsのUnicode変換処理が行われます。
Windowsは"〜=全角チルダ(#$FF5E)"という認識ですから、
#$301Cが変換できずに代替文字である"?"が表示されてしまいます。
# 上の書き方は紛らわしかったですね、スミマセン。
var
A: String;
W: WideString;
begin
W := #$301C;
A := W;
WをTextOutW等で直接描画すれば波ダッシュが描画されますが、
Aを表示させると"?"になってしまいます。
DEKO様
もにゃ様
いつもお世話になっております。
ちゃかです。
まずは無事正常動作しました事をご報告致します。
>>DEKO様
参考ページやソースまでコーディングしていただきありがとうございました。
UNICODEの解説も詳しくしていただき感謝しています。
>>もにゃ様
アドバイスありがとうございます。
知らないことでもそこから切り口が見つかる事も多くあると思いますので
またアドバイスをお願い致します。
今後の同一の問題の為にソース等を残しておきます。
皆様本当にありがとうございました。
またよろしくお願い致します。
管理人様貴重なスペースありがとうございました。
//--------------------------------------------------------
//以下問題解決ソース
//--------------------------------------------------------
(* 環境
・Windows Vista Bussiness
・Delphi 7 Professinal
・Oracle 10g
*)
{ 関数宣言 }
//「〜」文字変換関数 (「#$301C」 → 「#$FF5E」)
function F_WaveDashReplace(WS : WideString): String;
{ 関数処理 }
//=================================================
// 「〜」文字置換処理
//=================================================
function TForm1.F_WaveDashReplace(WS : WideString): String;
var
i : Integer;
begin
for i := 1 to Length(WS) do
begin
if WS[i] = #$301C then
begin
WS[i] := #$FF5E;
end;
end;
result := WS;
end;
//-----------------------------------------
// メイン処理
//-----------------------------------------
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('select * from test');
ADOQuery1.Open;
while ADOQuery1.Eof = False do
begin
//showmessage(ADOQuery1.FieldByName('text').AsString); ← このままでは「〜」文字が「?」に文字化け
showmessage(F_WaveDashReplace(ADOQuery1.fieldByName('text').AsVariant))
ADOQuery1.Next;
end;
ADOQuery1.Close;
end;
結果:DB上 ⇒ ShowMessage
・「あいう」⇒「あいう」
・「あ〜う」⇒「あ〜う」
・「あ?う」 ⇒「あ?う」
・「? / 〜」⇒「? / 〜」
・「〜 / ?」⇒「〜 / ?」
ツイート | ![]() |