アーキテクチャをスマートに。

株式会社ネオジニア代表。ITアーキテクトとしてのお仕事や考えていることなどをたまに綴っています。(記事の内容は個人の見解に基づくものであり、所属組織を代表するものではありません)

Excelシートに入力されたテキストと画像をSQLiteデータベースに登録する(3)

INSERT文でBLOBデータを登録する

SQLiteで BLOBをINSERT文で扱う方法を調べてみると、16進数文字列をx''で囲って記述するとよいことがわかりました。
以下のような感じ。

sqlite> CREATE TABLE table2 (id INTEGER, dat BLOB);
sqlite>
sqlite> INSERT INTO table2 (id, dat) VALUES (1, x'0003070b0f');
sqlite>
sqlite> SELECT id, hex(dat) FROM table2;
1|0003070B0F
sqlite>

なんや、こんな簡単に出来るんか。。。
ちょっと拍子抜け。
難しく考えすぎでした。

Byte() を16進文字列に変換する

VBScriptでは Byte() に対する操作はほとんど何も出来ません。
ネット上を少し検索すると、16進文字列をByte()に変換する方法が、以下のページにありました。
http://winscript.s41.xrea.com/wiki/index.php?%5B%5B%A5%C6%A5%AF%A5%CB%A5%C3%A5%AF%5D%5D

なにやら Microsoft.XMLDOM を使うと 16進文字列→Byte() に変換できる様子。なるほど。これを応用して逆の入出力をすれば、Byte()→16進文字列 の変換ができるのでは?

ということで作ったのがこの関数。

'-------------------------------------------------------------------------------
'バイト配列を16進文字列に変換する
'-------------------------------------------------------------------------------
Function ByteArray2HexText(byteArray) 
	With CreateObject("Microsoft.XMLDOM").createElement("tmp") 
		.DataType = "bin.hex" 
		.NodeTypedValue = byteArray 
		ByteArray2HexText = .Text
	End With 
End Function

これであっさりうまく行きました。引数に Byte() を渡すと16進文字列が返ってきます。

INSERT文を作ってSQLiteに流しこむ

あとは SQLite をShellExecで起動し標準入力に SQL を流しこんでやれば実行できそうです。

こんな感じです。

Option Explicit

Dim objFSO :Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
Dim objWshShell : Set objWshShell = WScript.CreateObject("WScript.Shell")


'データファイルのパス
Dim tempFilePath : tempFilePath = objFSO.BuildPath(objFSO.GetParentFolderName(WScript.ScriptFullName), "temp.jpg")

'データファイルをバイナリ読みこみ
Dim objStream : Set objStream = WScript.CreateObject("ADODB.Stream") 
objStream.Open : objStream.Type = 1
objStream.LoadFromFile tempFilePath
objStream.position = 0
Dim objBin : objBin = objStream.Read
objStream.Close


'sqlite3.exe を起動
Dim objWshExec : Set objWshExec = objWshShell.Exec("sqlite3.exe test.db")

'標準入力を取得
Dim sqlStream : Set sqlStream = objWshExec.StdIn

'SQLを書き込む
sqlStream.WriteLine "INSERT INTO table2 (id, dat) VALUES (2, x'" & ByteArray2HexText(objBin) & "');"

'テキストも書いてみる
sqlStream.WriteLine "INSERT INTO table2 (id, dat) VALUES (3, 'てすと');"

'SELECTしてみる
sqlStream.WriteLine "SELECT * FROM table2;"

sqlStream.Close

'SELECT結果を表示
MsgBox objWshExec.StdOut.ReadAll

'-------------------------------------------------------------------------------
'バイト配列を16進文字列に変換する
'-------------------------------------------------------------------------------
Function ByteArray2HexText(byteArray) 
	With CreateObject("Microsoft.XMLDOM").createElement("tmp") 
		.DataType = "bin.hex" 
		.NodeTypedValue = byteArray 
		ByteArray2HexText = .Text
	End With 
End Function

実際これでうまく行きました。

ただし、Linuxで見ると日本語が化けますSJISで入ってしまっているようです。

ガーン。

Windowsだけで使うのなら問題ないですが、このDBはAndroidで使うDBなので、これではまずいです。UTF-8に変換する必要があります。

次はUTF-8に変換する方法を考えます。