UTF8のデータをASPに表示

解決


taktak  2008-05-12 07:54:38  No: 139687

ASP(UTF8)でMySQL(5.0.51:UTF8)テーブルに格納されたUTF8データを取得して画面に表示させようとしていますが、文字化けのように表示されます。MySQLへの接続はMySQL-ODBC(3.51.25:UTF8)です。
ASP、MySQL、ODBCをUTF8で設定しているのですが、表示できない理由をご教授下さい。
例)テーブルの値(地方:E59CB0-E696B9)が、ASPでは(蝨ー譁:E59C-B0-E696)

■以下がソースです。
<% @CodePage="65001" Language="VBScript" %>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xml:lang="ja" lang="ja" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<link rel="stylesheet" type="text/css" charset="UTF-8" href="zaitakui.css" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<title>UTF8対応</title>
</head>
<BODY>
<FORM name="F_top" action="TOP.asp" method="post">
<%
  Response.Charset="UTF-8"
  call mySQLconnect("hogehoge")
  ssql="select * from t_sikyoku group by sikyokunum"
  call mySQLrecordset(rs0,ssql)
  
  do until rs0.eof
    response.write "【" &  rs0("sikyokumei") & "】"
  rs0.MoveNext
  loop
  
%>
<%
'DB接続
sub mySQLconnect(dsrc)
  set mySQLconn=Server.CreateObject("ADODB.Connection")
  mySQLconn.Open dsrc
  if Err.number <> 0 then
    Response.Write "接続エラー"
    Response.End
  end if
end sub

'DB切断
sub mySQLdisconnct()
  mySQLconn.Close
  Set mySQLconn=Nothing
end sub

'recordset
sub mySQLrecordset(byref RS,msql)
  Set mySQLcomm=Server.CreateObject("ADODB.Command")
  mySQLcomm.ActiveConnection=mySQLconn
  mySQLcomm.CommandText=msql
  Set RS=mySQLcomm.Execute
end sub

'Excute
sub mySQLExcute(msql)
  Set mySQLcomm=Server.CreateObject("ADODB.Command")
  mySQLcomm.ActiveConnection=mySQLconn
  mySQLcomm.CommandText=msql
  mySQLcomm.Execute
end sub
%>
</FORM>
</BODY>
</HTML>


魔界の仮面弁士  2008-05-12 22:45:50  No: 139688

まず、ASP のソースファイルは、UTF-8 で保存していますか?
また、それは BOM を含んでいますか? それとも含んでいませんか?
# IIS のバージョンによって、この BOM の扱いが違うようなので。

あとは、Session.CodePage がどうなっているのか、とか。

> 例)テーブルの値(地方:E59CB0-E696B9)が、ASPでは(蝨ー譁:E59C-B0-E696)
本来であれば、ASP 自体が UTF-8 であろうとなかろうと、
  S = RS.Fields("foo").Value
の結果は、"地方" すなわち "ChrW(&H5730) & ChrW(&H65B9)" であるべき
ところですが、これは完全にデータが破損していますね…。

UTF-8 バイナリ (E59CB0-E696B9) を、Shift_JIS でデコードした場合、その内容は
  E59C  蝨
  B0    ー(半角)
  E696  譁
  B9    ケ(半角)
の 4 文字になるはずです。

まだこの状態であれば、ただの文字化けであり、データ破損は起こしていないので
対処のしようもあったのですが、今回は E59C-B0-E696 に損失しているのですから、
もはや復元は不可能ですね…。

> 表示できない理由をご教授下さい。
ここなどの VB 系のコミュニティで聞くよりも、どちらかとえば、ここよりも
MySQL 系のコミュニティを利用された方が、直接的な回答が得られるかと思いますよ。

プログラム側に問題が無いとは言えませんが、文字化けとはあまり
関係無さそうな問題点しか見当たりませんでした。
どちらかといえば、環境設定やドライバ等の問題である気がします。

状況からみて、どこかで Shift_JIS への変換が走っているようなので、DB か ODBC に
「サーバーの文字コード設定をクライアントでもそのまま使う」ような設定やコマンドが
あれば解決できるのでしょう。ただ、私は MySQL は専門外なので答えられませんが…。

# 以下、本題とは関係無さそうなですが、一応ツッコミ。

面倒でも、Option Strict を宣言する事をお薦めします。
変数のスペルミスなどによる意図しないバグが混入する事を防ぐ事ができますので。

> <% @CodePage="65001" Language="VBScript" %>
> <?xml version="1.0" encoding="UTF-8"?>
それから、別件ですが重要な点。上記のような記述は、その時点で NG です。
これですと、XML 宣言の前に改行コードが入っているため、不正な XML となってしまいます。
@ ディレクティブ と XML 宣言の間に、余計な文字を含めないようにしてください。

> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
そして、こちらもまた NG です。
XHTML 1.0 Strict の DTD を宣言されていますが、その後に続く HTML データが
その DTD に従っていないため、これもまた文法的に不正です。

> response.write "【" &  rs0("sikyokumei") & "】"
テストコードだからかも知れませんが、これもまたマズイです。

まず、値を取得するために、既定のプロパティを使うべきではありません。
Collect プロパティまたは Value プロパティを使うようにしましょう。

それから、受け取ったデータをそのまま Response.Write する事は避けるべきです。
たとえば、データ中に HTML や XML として特別な意味を持つ値(<,",',&等々)が
含まれていると、表示データに問題が発生しますよね。
特に、今回のデータは XML なのですから、より厳密にならねばなりません。

>  if Err.number <> 0 then
この処理は無意味です。エラー処理が書かれていますが、肝心のエラートラップが
しかけられていませんので、この部分が処理される事はありません

>  Response.End
これも論外。エラーがあったからといって単純に End してしまうと、
出力結果が XML あるいは HTML の体裁を保てなくなりかねません。
異常時処理だからといって手を抜かないようにしましょう。

> sub mySQLrecordset(byref RS,msql)
記述するのであれば、むしろ msql 側に ByVal を付けるべきでしょうか。
VBScript の場合、引数の規定値は参照渡しですから、これでは冗長的です。

引数の渡し方を明示するのであれば、
  Sub mySQLrecordset(ByRef RS, ByVal msql)
または
  Sub mySQLrecordset(RS, ByVal msql)
となるべきですし、その違いを気にしない人なら(本来は気にするべきですが)
  Sub mySQLrecordset(RS, msql)
と書くでしょう。前者だけに ByRef が付くというのは、かなり違和感があります。

> mySQLcomm.ActiveConnection=mySQLconn
これ(Let 処理)でも動作しますが、ここは本来、Set で代入すべき処理です。

> Set mySQLcomm=Server.CreateObject("ADODB.Command")
> mySQLcomm.ActiveConnection=mySQLconn
> mySQLcomm.CommandText=msql
> mySQLcomm.Execute
問題はありませんが、これだけなら「mySQLconn.Execute msql」の一行で良いかも。


taktak  2008-05-13 00:06:26  No: 139689

魔界の仮面弁士様  よろしくお願いします。
>まず、ASP のソースファイルは、UTF-8 で保存していますか?
>また、それは BOM を含んでいますか? それとも含んでいませんか?
># IIS のバージョンによって、この BOM の扱いが違うようなので。
ASP のソースファイルはUTF-8(BOM付き)で保存しており、IISは6.0です。

>あとは、Session.CodePage がどうなっているのか、とか。
特に指定はしていませんでした。UTF8が必要なんでしょうか?

>> 例)テーブルの値(地方:E59CB0-E696B9)が、ASPでは(蝨ー譁:E59C-B0-E696)
訂正)テーブルの値(地方:E59CB0E696B9)が、ASPでは(蝨ー譁ケ:E59CB0E696B9)です。
私が1文字毎の方が分かりやすいかと勝手に-を付加していました。

># 以下、本題とは関係無さそうなですが、一応ツッコミ。
ご指摘ありがとうございます。先人が作っていた関数をそのまま解析もせずに使っていました。もう少し勉強します。

>> <?xml version="1.0" encoding="UTF-8"?>
>> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
上記2点は、特に必要ないということでしょうか?


魔界の仮面弁士  2008-05-13 09:07:13  No: 139690

まず、先の投稿の訂正。

>> Option Strict を宣言する事をお薦めします。
これは、"Option Strict" ではなく、"Option Explicit" の間違いです。m(_ _)m

> 魔界の仮面弁士様  よろしくお願いします。
私なんぞよりも、MySQL の専門家に尋ねるべき範囲ですよ…? (^_^;)
VB や ASP の範囲であればお答えできますが、私は、MySQL に関しては素人ですし。

ADO 側の 動的プロパティや、ODBC ドライバの設定、あるいは MySQL 自身の設定で
解決できる物なのか、それともそもそも解決方法が無い(Shift_JIS として処理するしか無い)
問題なのかすら、今の私には判断できません。

とりあえず、別の ODBC ドライバの場合はどうなるのでしょうか? たとえば…。
http://www.datadirect.co.jp/

それから—— ASP を介さず、ODBC + Unicode 対応ソフト(Microsoft Access 等)などでの
表示はできているのでしょうか。それが出来ていないのであれば、MySQL あるいは ODBC 固有の
問題の可能性が非常に高いので、ここで質問するのは、あまり望ましくないようにも思えます。

もし、それが出来ていて、ASP だけで化けてしまうという状況であるならば、VBS/ASP 側の
問題とも考えられるので、ここで続ける事には何の問題も無いと思います。

ただ、ここの掲示板で MySQL に詳しい VB 開発者の登場を待つことを止めはしませんが、
過去の MySQL + UTF-8 系の質問に対する回答状況を鑑みると、MySQL 系のコミュニティに
移動されるとか(よく知りませんが、www.mysql.gr.jp とか?)、MySQL + UTF-8 + ASP の
組合せを経験している開発業者やコンサルを探すなどした方が、解決への近道な気もします。
(それで本当に解決できるのかどうかは別として)

> ASP のソースファイルはUTF-8(BOM付き)で保存しており、IISは6.0です。
であれば、その点に関しては問題ないと思います。

>> あとは、Session.CodePage がどうなっているのか、とか。
> 特に指定はしていませんでした。UTF8が必要なんでしょうか?
Session.CodePage の既定値は、@ CODEPAGE ディレクティブの値ですので、
未設定であればそれでも構いません。これはたとえば、ソース自体は UTF-8 でも
  http://server/getCSV.asp?type=Shift_JIS
  http://server/getCSV.asp?type=UTF-8
などのようにして、「条件によって、別の文字コードで Response.Write するページ」を
作りたいような場合などに使われる機能です。

そしてこの設定は、セッション単位で有効なので、もし他の asp ページで設定されていた場合、
それらが引き継がれている可能性がある事に注意が必要です。

> 訂正)テーブルの値(地方:E59CB0E696B9)が、ASPでは(蝨ー譁ケ:E59CB0E696B9)です。
最後の B9 は欠けてはいないのですね? であれば、バイナリとして受け取った上で、
それを ADODB.Stream 等で変換することで、無理やりに読みとれる可能性はありますね。

ただし、「Shitt_JIS で定義されていない範囲のバイナリ」が含まれるような
UTF-8 データが返される場合について、十分にチェックしておく必要があるでしょう。

> 私が1文字毎の方が分かりやすいかと勝手に-を付加していました。
あ、それは勿論わかっています。その方が読みやすいですね。

>>> <?xml version="1.0" encoding="UTF-8"?>
>>> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
> 上記2点は、特に必要ないということでしょうか?
…必要あるかどうかは、こちらでは判断のしようが無いところです。

DOCTYPE 宣言に合わせて内容を修正すべきなのか、それとも DOCTYPE を修正すべきか
あるいは DOCTYPE 自体を除去するべきかは、そちらのシステムの仕様次第でしょうから、
分からないのであれば、当時の開発担当者に連絡を取って確認すべき事柄かと。

たとえば IE6 と IE7 と IE8β とでは、DOCTYPE の有無によって、レンダリングモードが
変化しますし、また、XML 宣言を付けるべきかどうかも異なってきます。

そうしたアプリ側の仕様を無視して、HTML / XHTML 文書自体の文法だけで話して良いのであれば、
DOCTYPE は本来必須です(多くのブラウザが、無い場合は独自判断で処理してくれますが)ので、
できれば削除すべきでは無いでしょう。別のDOCTYPE宣言に変える可能性はあるかも知れませんが。

そして DOCTYPE を付けた以上、「この文書は、正しい文法で記述されていますよ」という
意思表示であり、その中でも、厳密性の高い XHTML 1.0 Strict が選択されているのですから、
不適切な HTML 構造を書くのはよろしく無いでしょう。
http://www.atmarkit.co.jp/fxml/askxmlexpert/022xhtml/22xhtml.html

出来上がったサイト(ASP の実行結果)を
http://openlab.ring.gr.jp/k16/htmllint/htmllint.html
に書けて、文法チェックを行われる事をお薦めします。

なお、XML 宣言の前に改行を入れないというのは、たとえば
<% @ CodePage="65001" Language="VBScript" %>
<?xml version="1.0" encoding="UTF-8"?>
ではなく、
<% @ CodePage="65001" Language="VBScript" %><?xml version="1.0" encoding="UTF-8"?>
としなければならない、という事です。

また、Option Explicit 宣言を付ける場合、それはたとえば
<% @ CodePage="65001" Language="VBScript" %><%Option Explicit
%><?xml version="1.0" encoding="UTF-8"?>
などのようにすることができます。


taktak  2008-05-14 02:35:55  No: 139691

>私なんぞよりも、MySQL の専門家に尋ねるべき範囲ですよ…? (^_^;)
名前指定で記述してしまい申し訳ございません。解決を焦って配慮を欠いてました。またMySQLの質問にかたより過ぎていますので、この場所はご指摘の通り適していませんね。

>ADO 側の 動的プロパティや、ODBC ドライバの設定、あるいは MySQL 自身の設定で
>解決できる物なのか、それともそもそも解決方法が無い(Shift_JIS として処理するしか無い)
問題をもう少し掘りさげ調べてみます。また、その他の質問にも丁寧に回答していただきありがとうございます。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加