[三流君] −−> [ASPで遊ぶ、失敗する] −−> [バックナンバー一覧]
−−> No.97 UTF-8の変換処理(エンコード)に挑戦してみた

UTF-8の変換処理(エンコード)に挑戦してみた

VBA UTF-8 で 誤爆してGoogleからの来場者が多いので、先頭に書きます。
VBAからJavaScriptを使う方法もありますよ。

スクリプト コントロールの概要
https://www.microsoft.com/japan/msdn/scripting/scriptcontrol/scoverview.htm
↑MSのサイトだけど、httpとhttpsが混在してると警告が出るけどビックリしないでね。
頭の例は、MSが大好きなVBScriptだけど、.Language = "JScript" も可能と途中で書いてありました・・・。
なんて↑へんな日本語で書くよりコード↓を見た方が伝わりやすいですよね。
Sub JavaScript_Test() 'VBA から VavaScriptを使うテスト

    '検索文字を入力
    Dim strMOJI As String
    strMOJI = InputBox("キーワード=", "入力", "三流")

    '検索文字をJavaScriptのencodeURI関数で作る
    Dim strPARA As String  'パラメーター
    Dim sc As Object
    Set sc = CreateObject("ScriptControl")
    sc.Language = "Jscript"  'JavaScriptを指定(書き間違えないでね)
    strPARA = sc.CodeObject.encodeURI(strMOJI) 'encodeURI関数を呼ぶ
    Set sc = Nothing
    Debug.Print strPARA
    
    '手抜きで Shell でWebページを表示する
    Dim strURL As String
    strURL = "http://www.google.co.jp/search?hl=ja&ie=UTF-8&q=" & strPARA
    Call Shell("explorer.exe """ & strURL & """", vbNormalFocus)

End Sub
↑こんな感じで、使えるので、活用してみてください。VBAからJavaScriptを使って処理する感じです。
※※上記でほぼ解決なのですが、下記、メルマガで書いた使えない、冗長な自作関数です。



本文(発行内容)


UTF-8の変換処理(エンコード)に挑戦してみた

こんにちは、三流プログラマーのKen3です。

今回は、
UTF-8の変換処理(エンコード)にチャレンジしてみました。

/* * 1.今回のキッカケ */

下記のような、訪問者保存のプログラムを組んでログの解析をしてます。 HTML側に <script language=javascript> document.write ("このページの更新日は、" + document.lastModified +"です<BR>"); var Referrer=window.document.referrer; if (window.navigator.appName=='Netscape'){ if(parseInt(window.navigator.appVersion)> 4 ){ document.write ("<img src='/cgi-bin/cnt/cnta.asp?Referrer="+Referrer+"'>");} }else{ document.write ("<img src='/cgi-bin/cnt/cnta.asp?Referrer="+Referrer+"' style=\"display\:none\"> ");} </script> と、 画像の処理に見せかけて、cnta.aspをコールして、 ^^^^^^^^^^^^^^^^^^^^^^^ cnta.aspで、 WTIME = Now '現在時刻の代入 IP = Request.ServerVariables("REMOTE_ADDR") URL = Request.ServerVariables("HTTP_REFERER") referrer = Mid(Request.ServerVariables("QUERY_STRING"), 10) を書き込んでます。 http://www.ken3.org/cgi-bin/cnt/log100.asp で、リンク元などを確認してます。 リンク元をみてみると、 http://www.google.co.jp/search?q=%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB などのコードが保存されてます。 q=が検索文字列だと思うのですが、 E38395ってなんだ?どうしても変換方法が見つかりませんでした また、別のログデータからコード体系らしい部分を見ると、 ie=utf8&oe=utf8&querytime=8TuE& このUTF8ってのが怪しそうです。

/* * 2.UTF-8のデータ構造を調べてみた */

ネタをバラすと、バイナリの保存を調べていたら、 たまたま、UTF8の記事を見かけたので脱線発行してます。 ※廃刊にした有料版のメルマガをベースにして発行してます。 話が噛み合わないところは、気にしないで下さい。 何を見たか?下記のようなコードの表を見ました。 http://www.asahi-net.or.jp/~CI5M-NMR/w3/rfc2279.txt より UCS-4 range (hex.) UTF-8 octet sequence (binary) 0000 0000-0000 007F 0xxxxxxx 0000 0080-0000 07FF 110xxxxx 10xxxxxx 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx 0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx と、変換表(規則)が書いてあった。 ※binaryの単語で引っかかったと思う。 これを見て、手で変換してみた。 http://www.google.co.jp/search?q=%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB がファイルを指定してます。 %E3%83%95 フ %E3%82%A1 ァ %E3%82%A4 イ %E3%83%AB ル とUTF-8でコード付けされてます。 ファイルの[フ]がE3 83 95かぁこれを2進数に直すと。 E 3 8 3 9 5 1110 0011 1000 0011 1001 0101 となります。 ここから、 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx の規則でxxxxの実データを取り出すと(1110 10 10は固定のコードなので) E 3 8 3 9 5 1110 0011 1000 0011 1001 0101 xxxx xx xxxx xx xxxx から xの部分を取り出すと、 0011 00 0011 01 0101 となり、わかりやすく、 0011 0000 1101 0101 として16進に直すと 30D5となるが、これはUNICODEらしい。 これをシフトJISに変換すれば、 UTF-8のデータを取り出せそうです。

/* * 3.UNICODEと言われてもなぁ ASCW関数で単純に変換してみた */

UNICODEと言われてもなぁ、どうやって変換するんだろう? 悩んでいたら、ASCWとCHRWがUnicode コード ポイントをやり取りするみたいです。 ASCとASCW関数 http://www.microsoft.com/japan/msdn/library/ja/vblr7/html/vafctasc.asp CHRとCHRW関数 http://www.microsoft.com/japan/msdn/library/ja/vblr7/html/vafctchr.asp に書いてありました。 ASC関数とASCW関数の違いを見るために、 下記の確認プログラムを作ってみました。 単純にASCとASCWで変換しただけですが。 CHK_DATA = Request.QueryString("DATA") 'パラメータの代入 '長さをチェックする If Len(CHK_DATA) <> 0 Then '文字が入っていたら Response.Write "受け取ったデータは[<b>" Response.Write Server.HTMLEncode(CHK_DATA) & "</b>]です<br>" '結果をテーブルで表示する Response.Write "<table border=1><tr>" Response.Write "<th>n文字目</th>" Response.Write "<th>調査する文字</th>" Response.Write "<th>ASC結果(16進)</th>" Response.Write "<th>ASCW結果(16進)</th>" Response.Write "</tr>" & vbCrLf '文字数分ループして、コードを表示 For n = 1 To Len(CHK_DATA) Response.Write "<tr>" Response.Write "<td>" & n & "</td>" strWORK = Mid(CHK_DATA, n, 1) 'n番目の文字を取り出す Response.Write "<td>" & Server.HTMLEncode(strWORK) & "</td>" Response.Write "<td>" & Hex(Asc(strWORK)) & "</td>" 'ASCで変換 Response.Write "<td>" & Hex(AscW(strWORK)) & "</td>" 'ASCWで変換 Response.Write "</tr>" & vbCrLf Next Response.Write "</table>" & vbCrLf End If 三流君ASPを変換すると、下記でテストすると、 http://www.ken3.org/cgi-bin/test/test097-1.asp?DATA=%8EO%97%AC%8CNASP n文字目 調査する文字 ASC結果(16進) ASCW結果(16進) 1 三 8E4F 4E09 2 流 97AC 6D41 3 君 8C4E 541B と変換されます。 おっと、確認したいのは、ファイルのフのコードだった、 http://www.ken3.org/cgi-bin/test/test097-1.asp?DATA=%83t%83@%83C%83%8B で確認すると、 n文字目 調査する文字 ASC結果(16進) ASCW結果(16進) 1 フ 8374 30D5 2 ァ 8340 30A1 3 イ 8343 30A4 4 ル 838B 30EB と表示されました。 30D5のコードにやっとたどり着きました。

/* * 4.SJISをUTF-8に直す */

さてと、 では、本題の何も意識しないで使用しているシフトJISをUTF-8に直してみます。 SJISをASCW関数でUNICODEに変換してから、 そのコードを2進数に直す。 2進数を固定のビットを立てたコードに当てはめて、 再び16進数に戻す。そのとき%を付けた文字列にする。 なんか、かったるいけど、チャレンジしてみます。 三流君ASP http://www.ken3.org/cgi-bin/test/test097-2.asp?DATA=%8EO%97%AC%8CNASP で AB型 三流 http://www.ken3.org/cgi-bin/test/test097-2.asp?DATA=AB%8C%5E+%8EO%97%AC テストできます。 ソースは長いけど、 下記のような感じです。 ポイントは、ASCWでUNICODEにして、2進数に変換後、 変換した16ビットを 'xxxx xxxx xxxx xxxx を下記に割り当てる '1110xxxx 10xxxxxx 10xxxxxx と、指定位置に割り当てただけです。 test097-2.asp <%@LANGUAGE=VBScript%> <html> <head> <title>文字コード関係で遊ぶ SJISからUTF-8へ変換テスト</title> </head> <body> <h1>文字コード関係で遊ぶ SJISからUTF-8へ変換テスト</h1> <br> 受け取った文字列に対して、<br> ASCW関数でUNICODEにして、それをオリジナルのUTF-8変換関数を使い、変換します<br> ※詳細は、ソースと詳細解説のページを見てください。<br> テストでgoogleの検索リンクを作成しました<br> <hr> <% CHK_DATA = Request.QueryString("DATA") 'パラメータの代入 '長さをチェックする If Len(CHK_DATA) <> 0 Then '文字が入っていたら Response.Write "受け取ったデータは[<b>" Response.Write Server.HTMLEncode(CHK_DATA) & "</b>]です<br>" '結果をテーブルで表示する Response.Write "<table border=1><tr>" Response.Write "<th>n文字目</th>" Response.Write "<th>調査する文字</th>" Response.Write "<th>ASC結果(16進)</th>" Response.Write "<th>ASCW結果(16進)</th>" Response.Write "<th>UTF8結果(%付16進)</th>" Response.Write "</tr>" & vbCrLf '文字数分ループして、コードを表示 strUTF8 = "" '空文字で初期化 For n = 1 To Len(CHK_DATA) Response.Write "<tr>" Response.Write "<td>" & n & "</td>" strWORK = Mid(CHK_DATA, n, 1) 'n番目の文字を取り出す Response.Write "<td>" & Server.HTMLEncode(strWORK) & "</td>" Response.Write "<td>" & Hex(Asc(strWORK)) & "</td>" 'ASCで変換 Response.Write "<td>" & Hex(AscW(strWORK)) & "</td>" 'ASCWで変換 '2バイト、漢字か判断 手抜きでLen関数で文字数を見た If Len(Hex(Asc(strWORK))) <= 2 Then If Asc(strWORK) <= &H20 Then '制御コードか? strCODE = "%" & Right("0" & HEX(ASC(strWORK)), 2) Else '英数はそのまま+する strCODE = strWORK End If Else strCODE = SJIStoUTF8(strWORK) '変換関数を呼ぶ End If Response.Write "<td>" & strCODE & "</td>" '結果を表示 strUTF8 = strUTF8 & strCODE '結果の文字列をつなげる Response.Write "</tr>" & vbCrLf Next Response.Write "</table><hr>" & vbCrLf Response.Write "受け取ったデータ[<b>" Response.Write Server.HTMLEncode(CHK_DATA) & "</b>]が<br>" Response.Write Server.HTMLEncode(strUTF8) & "となります<br>" Response.Write "テストでGoogleでコードをq=で指定してみます<br>" strURL = "http://www.google.co.jp/search?hl=ja&ie=UTF-8&q=" & strUTF8 Response.Write "<a Href='" & strURL & "' target='_blank'>" Response.Write Server.HTMLEncode(strURL) & "</a><br>" Response.Write "↑をクリックすると?チャント飛べましたか?" & vbCrLf End If %> <HR> <FORM ACTION="test097-2.asp" METHOD="GET"> 調査したい文字列を入力してください。<br> <INPUT TYPE="text" SIZE="30" NAME="DATA" VALUE="<%=CHK_DATA%>"> <INPUT TYPE="submit" VALUE="コード調査開始"><br> ↑いろいろと遊んでみてください↑ </FORM> <br> </body> </html> <% 'UNIコードの文字列を受け取り、UTF8コードの%付文字列を返す
Function SJIStoUTF8(strSJIS)

    strUNICODE = ASCW(strSJIS)  'ASCWでユニコードにする

    'コードを2進にしてワークに代入する
    strWORK2 = HEX16toSTR2(HEX(strUNICODE))

    '切り取って、UTF8の2進数を作成する
    'xxxx xxxx xxxx xxxx を下記に割り当てる
    '1110xxxx 10xxxxxx 10xxxxxx
    strUTF8CODE = "1110" & Mid(strWORK2, 1, 4)
    strUTF8CODE = strUTF8CODE & "10" & Mid(strWORK2, 5, 6)
    strUTF8CODE = strUTF8CODE & "10" & Mid(strWORK2, 11, 6)

    '作成した2進数を16進数に戻す
    strWORK16 = STR2toHEX16(strUTF8CODE)

    '%を付けて格納
    strRET = ""  'リターン値を初期化
    strRET = strRET & "%" & Mid(strWORK16, 1, 2) '%を付けた文字列を作成
    strRET = strRET & "%" & Mid(strWORK16, 3, 2) 
    strRET = strRET & "%" & Mid(strWORK16, 5, 2) 

    'リターン値を代入
    SJIStoUTF8 = strRET

End Function
'HEX16進文字列を受け取り2進数文字列を返す
Function HEX16toSTR2(strHEX)

    Dim n       'ループカウンタ
    Dim i       'ループのカウンタ
    Dim n8421   '8 4 2 1の数値計算用
    Dim str2STR 

    Dim nCHK

    str2STR = ""  '結果のエリアを初期化する

    '文字数分ループする
    For n = 1 To Len(strHEX)
        On Error Resume Next   'エラー発生時次の行へ
        nCHK = 0 '0で初期化
        nCHK = CInt("&h" & Mid(strHEX, n, 1)) 'n文字目を数値変換
        On Error Goto 0        'エラー処理を通常に戻す

        n8421 = 8  '初期値に8を代入する(上からチェックしたいので)
        For i = 1 To 4  '4回まわるよ
            If (nCHK And n8421) = 0 Then 'Andでビットをチェックする
                str2STR = str2STR & "0"  'ビットは立ってないよ
            Else
                str2STR = str2STR & "1"  'ビットは立ってるよ
            End If
            '次のビットをチェックしたいので2で割る
            n8421 = n8421 / 2
        Next 
    Next

    'リターン値をセットして終了
    HEX16toSTR2 = str2STR

End Function
'2進文字列を受け取り16進文字列を返す
Function STR2toHEX16(str2)

    Dim strHEX
    Dim n       'ループカウンタ
    Dim i       'ループのカウンタ
    Dim n8421   '8 4 2 1の数値計算用
    Dim nBYTE

    '頭4文字単位かチェックする
    n = Len(str2) Mod 4      '足りない文字数を計算する
    If n <> 0 Then 
       str2 = String(4 - n, "0") & str2 '頭に文字0を追加する
    End If

    strHEX = ""   '結果のエリアを初期化する

    '文字数分ループする
    For n = 1 To Len(str2) Step 4  '4文字(1バイト)単位にループを作る
        n8421 = 8  '初期値に8を代入する(上から計算したいので)
        nBYTE = 0  '1バイト計算用変数を初期化
        For i = 0 To 3  '4回まわるよ(4ビット分)
            'ビットが立っているかチェックする
            If Mid(str2, n + i, 1) = "1" Then
                nBYTE = nBYTE + n8421   'ビットに対応した数値を+する
            End If
            '次のビットを計算したいので2で割る
            n8421 = n8421 / 2
        Next 
        '計算して、1倍との数値が完成したので16進文字にしてセットする
        strHEX = strHEX & Hex(nBYTE)
     Next 

     'リターン値をセットして関数を抜ける
     STR2toHEX16 = strHEX

End Function
%>

/* * 5.終わりの挨拶 </HTML> */

今回は、 Googleなどのパラメータでよく見かける、UTF-8のコードを探ってみました。 自作のコードなので穴がありますが、何かの参考になれば・・・うれしいです。 ほかにも、amazon.comなどがUTF-8を使ってます。 転職をキーワードにしたリンクだと、 search?tag=ken3book-22&keyword=%E8%BB%A2%E8%81%B7&mode=blended と、tag=が自分のIDで次のkeyword=がUTF-8で指定したキーワードです。 動的に変更したキーワードのページを作るなら、test097-2.aspを応用して、 test097-3.aspを作成してみました。 儲かる http://www.ken3.org/cgi-bin/test/test097-3.asp?DATA=%96%D7%82%A9%82%E9 娘。 http://www.ken3.org/cgi-bin/test/test097-3.asp?DATA=%96%BA%81B 転職 http://www.ken3.org/cgi-bin/test/test097-3.asp?DATA=%93%5D%90E なんて感じで、ASPでキーワードを受け取り反応するプログラムを作れたり、 応用すれば、DBで人気キーワードを管理して、うまく使えるかも。 ※その応用ネタが難しかったりするんだけど・・・ 何かの参考となれば幸いです。 ASP、VBScript勉強中の三流プログラマーのKen3でした。


ページフッター

ここまで、読んでいただきどうもです。目的の情報が見つかったか?少々心配しつつ、、、

三流君へ メッセージを送る

感想や質問・要望・苦情など 三流君へメッセージを送る。
返信例 XXXXさんへ
下記のフォームからメッセージを送ることができます。


あなたのお名前(ニックネーム):さん
返信は?:

アドレス:に返事をもらいたい
感想や質問↓:


(感想や質問・要望・苦情はHPで記事に載せることがあります。)

種類別のリンク や 広告など

[三流君(TOP ken3.org へ戻る)] / [ASPで遊ぶ、失敗する] / [ASP記事 バックナンバー目次]


Blogとリンク:[三流君のMemo別館]/ [ASP 三流君のソースコード置き場]/ [Ken3Video YouTubeで動画解説]
広告:

気になった ジャンル ↓を選択してください。

まぁ、基本はデータの受け取りかなぁ。
・[Form等を使用したデータのやり取り]・・・ASPと言っても、HTMLの入力フォームからデータを受け取ります。POSTやGETでやりとりを押さえますか。

次は、データの入出力 で ADOを使った(ADOで接続) と SQLの解説を少々
・[ADOでMdbファイルを使う]・・・MDBと接続して、簡単な追加・更新・削除を行った。
・[ADOでExcelと接続してみた]・・・.xlsと接続してSQLを使ってみた。
・[ADOでCSVと接続してみた]・・・.CSV テキストを読み出した。※更新・削除はできません

広告:



DBが使えるので、あまり使用しないけど、普通のテキストファイル処理
・[テキストファイル処理]・・・ファイルを開いて、書き込む。1行読み込みなどを軽く

VBScriptでFormat関数が無いなど、微妙にVBAと違うけど
[VBScript関数関係の説明]・・・少し、処理を書いてみた。
[その他処理サンプル]・・・あまり良いサンプル作れなかったけど。。。
何かの参考となれば幸いです。



[三流君(TOP ken3.org へ戻る)] / [ASPで遊ぶ、失敗する] / [ASP記事 バックナンバー目次]


広告: