[三流君] −−>
[ASPで遊ぶ、失敗する] −−>
[バックナンバー一覧]
−−> No.99 UTF-8からSJISの変換処理(デコード)に挑戦してみた
UTF-8からSJISの変換処理(デコード)に挑戦してみた
本文(発行内容)
UTF-8からSJISの変換処理(デコード)に挑戦してみた
こんにちは、三流プログラマーのKen3です。
今回は、UTF-8からSJISの変換ルーチンを自作してみます。
いつもの三流的なアプローチなので、実際はアレンジして使ってください。
/*
* 1.今回のキッカケ
*/
SJISからUTF-8の変換をボロボロになりながら作りました。
三流君ASP http://www.ken3.org/cgi-bin/test/test097-2.asp?DATA=%8EO%97%AC%8CNASP
娘。 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
など、自作のSJISからUTF-8の変換ルーチンを作って回しました。
今回は、逆の、UTF-8からSJISの変換ルーチンを自作してみます。
また、自作するの?encodeURIの逆、デコードURIは使わないの?
※自作が好きなんで・・・
/*
* 2.UTF-8コード と 変換処理の構想
*/
検索キーワード忘れましたが、
下記のようなコードの対応表を発見しました
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の単語で引っかかったと思う。
2バイト文字(漢字)は、
1110xxxx 10xxxxxx 10xxxxxx
と、なります。
これを、xxの部分をまとめてると、UNIコードになるので、
それをCHRW関数でSJISに戻してます。
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.ログDBからUTF-8コードを変換してみた(サンプル作成)
*/
http://www.ken3.org/cgi-bin/cnt/log100.asp?MODE=ETC
で、通販ページのログを取ってます。
このデータを変換して、検索キーワードを表示させてみたいと思います。
テストで上に元のgoogleの検索リンク、下に変換結果を作成しました
http://www.ken3.org/cgi-bin/test/test099-1.asp
でテスト可能です。
ソースとデータを見て確認してください。
<%@LANGUAGE=VBScript%>
<html>
<head>
<title>文字コード関係で遊ぶ UTF-8からSJISへ変換(検索キーワードを戻す)</title>
</head>
<body>
<h1>文字コード関係で遊ぶ UTF-8からSJISへ変換(検索キーワードを戻す)</h1>
<br>
ログファイルから、UTF-8のキーワードを戻してみます。<br>
※詳細は、ソースと詳細解説のページを見てください。<br>
テストで上に元のgoogleの検索リンク、下に変換結果を作成しました<br>
<hr>
<%
'ADO DB Connection オブジェクトを作成
Set db=Server.CreateObject("ADODB.Connection")
db.Provider = "Microsoft.Jet.OLEDB.4.0"
'接続DBの位置を渡し、DBオープン
strDB = "../test/cnt_etc.mdb"
db.ConnectionString = Server.MapPath(strDB)
db.open 'データベースをオープンする
'お約束のレコードセットの作成 テーブル名logから全項目(*)を指定
'UTF-8のデータをLikeで選択する
strSQL = "Select * From log Where referrer Like '%UTF-8%' "
strSQL = strSQL & " ORDER BY WriteTime DESC"
Set rs = db.Execute(strSQL)
'データの表示を行う
Response.Write "発行するSQL:" & strSQL & "<hr>"
'EOFまでループ or 10件まで
nCNT = 1
Do While rs.EOF = False And nCNT <= 10 '.EOFがFalseで10以下の間
'リンク元の表示
Response.Write "変換前:<A HREF='" & rs.Fields.Item("referrer") & "'>"
Response.Write rs.Fields.Item("referrer") & "</A><BR>"
'%付のUTF-8コードを変換してみた
Response.Write "変換後:" & KANJI_HENKAN(rs.Fields.Item("referrer"))
Response.Write "<BR><BR><HR><BR>"
'次のレコードにポインタを移動する
rs.MoveNext 'これを忘れると悲惨なことに、、、
'カウンタを増やす
nCNT = nCNT + 1
Loop
'開いていたレコードセットを閉じる
rs.Close
'データベースも閉じようよ
db.Close
'お行儀よくオブジェクトも開放しましょう(通常は自動的に解放されるけど)
Set db = Nothing
'テストで終了時刻の表示
Response.Write "終了:" & Now() & "<hr>"
%>
</body>
</html>
<% '変換サブルーチンをまとめる
'%の後ろを強引に(手抜きで)変換してみた
Function KANJI_HENKAN(strMOJI)
Dim strRET
strRET = "" 'リターン値を初期化する
'特殊文字を手抜きでReplace関数で置き換える
strWORK = strMOJI
strWORK = Replace(strWORK, "%3F", "?")
strWORK = Replace(strWORK, "%2F", "/")
strWORK = Replace(strWORK, "%3A", ":")
strWORK = Replace(strWORK, "%3D", "=")
strWORK = Replace(strWORK, "%26", "&")
'+をスペースに変換したいけど、今回はそのまま。
strMOJI = strWORK '特殊文字変換結果の代入
'文字単位でループする
For n = 1 To Len(strMOJI)
strCHK = Mid(strMOJI, n, 1) '1文字取り出す
If strCHK = "%" Then '%の後ろをデコードするかチェック
strWORK = Mid(strMOJI, n, 9) '9文字取り出し変換処理へ渡す
strRET = strRET & UTF8toSJIS(strWORK) '変換結果を+する
n = n + 8 '強引に8文字飛ばす
Else 'そのまま
strRET = strRET & strCHK 'そのまま+する
End If
Next
KANJI_HENKAN = strRET
End Function |
Function UTF8toSJIS(strCODE)
'%E6%96%87 の UTF-8コード文字列をSJISに直す
Dim strHEX
Dim n 'ループカウンタ
Dim i 'ループのカウンタ
Dim str2CODE '2進数の文字列
Dim str2UNI 'UNICODE2進数
'1コード目を変換
strHEX = Mid(strCODE, 2, 2) '%を抜かしたコードを取得
str2CODE = HEX16toSTR2(strHEX)
'2コード目を変換
strHEX = Mid(strCODE, 5, 2) '%を抜かしたコードを取得
str2CODE = str2CODE & HEX16toSTR2(strHEX)
'3コード目を変換
strHEX = Mid(strCODE, 8, 2) '%を抜かしたコードを取得
str2CODE = str2CODE & HEX16toSTR2(strHEX)
'コードを抜き出しコピーする
'0 1 2
'1234 5678 9012 3456 7890 1234
'1110 xxxx 10xx xxxx 10xx xxxx を下記に割り当てる
'xxxx xxxx xxxx xxxx
str2UNI = Mid(str2CODE, 5, 4)
str2UNI = str2UNI & Mid(str2CODE, 11, 6)
str2UNI = str2UNI & Mid(str2CODE, 19, 6)
'作成した2進数を16進数に直す
strHEX = STR2toHEX16(str2UNI)
'16進数文字列を数値に直し、さらにChrW関数でSJISに
UTF8toSJIS = ChrW(CInt("&H" & strHEX))
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)
nCHK = 0 '0で初期化
On Error Resume Next 'エラーを無視する
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 |
%>
/*
* 4.終わりの挨拶 </HTML>
*/
今回は、%付のUTF-8コードを戻してみました。
これで、ログで収集したGoogleからの来場者が使用したキーワードがわかりそうです。
ほかのコードも戻して、ログキーワード解析につなげたいですね。
無駄な部分多いですが、変換処理の一つの案として、受け取ってください。
何かの参考となれば幸いです。
ASP、VBScript勉強中の三流プログラマーのKen3でした。
フィードバック
ASP系の→[掲示板]←を覗く、質問を書き込む
評価・感想
三流君の主なリンク先
[アクセスランキング]
[サイトマップ]
[リンク先・相互リンク先など]
Ken3の日記(weblog) --
[プログラマー業務の愚痴]
[VBA系の話題]
[ASP系の話題]
[コンビニ系ネタ]
[その他]
その他 宣伝広告