■ ADODB.StreamのUTF-8読み書き
VBS自体は使えなくなるかもしれないんですがVBAや他の言語でも使えるので一応備忘
基本的にテキストの読み書きはFileSystemObjectを使うのですがShift-JISしか使えません。
今回はWebページのヘッダーのメタタグの機械的な変換をしたいなぁと思った時にWebページは全部UTF-8に移行済みだったので、じゃあ「ADODB.Stream」という事ですね。
ADODB.Streamで出来る事は主に2つ、文字コード指定してのテキストの読み書きとバイナリデータの読み書きです。
■UTF-8を読み込む
まずは読み込みから
htmlpath="c:\makewebsite\test.html"
With CreateObject("ADODB.Stream"):.Type = 2:.Charset = "UTF-8":.Open:.LoadFromFile htmlpath:html = .ReadText:.Close:End With
- 通常通りCreateObjectでオブジェクトを作ります。
- Typeは1がバイナリモード、2がテキストモードです。
- Charsetは文字コード、今回はUTF-8のhtmlを読み込むので UTF-8です。
- Openでストリームを開きます
- LoadFromFile にファイルパスを指定
- ReadTextでhtmlの内容を全て取得
- Closeでストリームを閉じます
■UTF-8で書き込み①
次に書き込み
htmlpath="c:\makewebsite\test.html"
retext="書き込む文字"
With CreateObject("ADODB.Stream"):.Type = 2:.Charset = "UTF-8" :.Open:.WriteText retext:.SaveToFile htmlpath, 2:.Close:End With
これでOK!単純に先ほど逆順に処理します
- CreateObject(ストリームオブジェクト)
- Type(2:テキストモード)
- Charset(文字コード:UTF-8)
- Openでストリームを開きます
- WriteText でストリームに書き込む
- SaveToFile でストリームを全て出力、2は上書き
- Closeでストリームを閉じます
■Byte Order Mark/バイトオーダーマーク
ただし、1つだけ問題があります。
ADODB.Streamの仕様上書き込みにはBOM(ばいとおーだーまーく)が入ります。
これが何かというとファイル先頭の3byteを使ってテキストの種類を書き込みます。
通常あっても基本問題ありませんが、現在の主流はテキストの内容を見て自動判断する方式です。windows10以降のデフォルト保存形式もUTF-8BOMなしです。
そしてwebで扱うHTMLもBOMは不要です。
普通のテキスト同じく基本的には問題ないものの、頭に3byteがクローラーなどの邪魔になる可能性がありBOMは消す必要があります。
■UTF-8で書き込み②(BOMなし)
With CreateObject("ADODB.Stream")
.Type = 2:.Charset = "UTF-8":.Open:.WriteText retext:.Position = 0:.Type = 1:.Position=3:tb=.Read:.Close
.Type = 1:.Open:.Write tb:.SaveToFile htmlpath, 2:.Close
End With
- CreateObject(ストリームオブジェクト)
- Type(2:テキストモード)
- Charset(文字コード:UTF-8)
- Openでストリームを開きます
- WriteText でストリームに書き込む
- テキストの状態でストリームの位置を0に
- Type(1:バイナリモードに変更)
- バイナリモードで開始位置を3byte移動
- Readで変数に4byte以降代入
- Closeでストリームをリセット
- Type(1:バイナリモード)
- Openでストリームを開きます
- Writeでストリームを書き込む
- SaveToFile でストリームを全て出力(2は上書き)
- Closeでストリームを閉じます
公式ドキュメントを見る限りCloseで閉じた後に再度Openで開いても問題なさそうなので1つのストリームでBOMを消しています。
処理が複雑そうになるならストリームは読み込みと書き込みで分けてください。
処理としては文字列情報をテキストストリームに変換
UTF-8でテキストストリームに書き込むとBOMが入る
テキストストリームの状態でポジションを0で先頭に戻す
バイナリモードにして先頭からBOM分の3byteをスキップさせ変数にbyteで代入
ストリームを切断後に開きなおし、ストリームにbyteを代入あとはSaveToFileで出力して終了。
■UTF-8で書き込み③(BOMなし)
With CreateObject("ADODB.Stream")
.type=2:.charset="UTF-8":.open:.writetext retext
.position=0:.type=1:.Position=3:tb=.Read
.position=0:.seteos:.write tb:.SaveToFile htmlpath, 2:.Close
End With
もう少し詰めるならこう。
BOM3byteを飛ばすところまでは同じ。
ストリームの位置を先頭に戻し、seteosでストリーム内容を完全消去します。
そこにストリームを書き込みなおして出力。
コードの評価をジェミニなどで通したときにBOMが必ずつくか分からないと言われて調べたけれど、BOMが付かない状況を探しても見つかりませんでした。
WriteText メソッド (ADO)
https://learn.microsoft.com/ja-jp/office/client-developer/access/desktop-database-reference/writetext-method-ado
Charset プロパティ (ADO)
https://learn.microsoft.com/ja-jp/office/client-developer/access/desktop-database-reference/charset-property-ado
そもそもBOMについての記載がなく、仕様説明ないまま使われてる技術怖い・・・。
0 件のコメント:
コメントを投稿