JavaScriptでファイルの書き込みをUTF-8で行う(htaまたは、wsh用)

Windowsデフォルトの機能だけで、ファイルの読み書きを行いたい場合にはhtawshを使う必要があります。一般的に知られているのはFileSystemObjectというActiveXObjectを生成して、そのオブジェクトを通してファイルの読み書きを行うのですが、これが自由度が少なく、Shift_JISでしか扱ってくれません。

ADODB.Streamなら他のエンコーディングも扱える

いろいろググって見るとADODB.Streamというのが使えるらしい。じゃあ簡単だと思いやっつけで書いてみたら書き出せた。

と思っていたらBOMに悩まされる

なんかエディタの挙動が違うなぁと思っていたら、なんかUTF-8(BOM)とか書いてあります。何じゃこれってことで調べてみるとUTF-8の場合、ファイルの最初に3バイトにByte Order Markというものがついていて、それが悪さをしているらしい。どうやったら書き出せるか調べてみた。

VBScriptばっかり

そもそもJavaScriptってWindows界隈では人気ないのね。。。で、しかもVBScriptでもまさにこれって事をやってる人がいないので、試行錯誤の上データをUTF-8(BOMなし)で出力する関数を書いてみた。ドキュメントはあんまりないし、ググってもなかなかでてこないので、苦労した。で、結果が下のソースコードhtaのサンプルにもリンクを貼っておくので、自己責任で使用してください


// この関数がファイルを保存する関数
var saveFile = function(filename, text) {
// ADODB.Streamのモード
var adTypeBinary = 1;
var adTypeText = 2;
// ADODB.Streamを作成
var pre = new ActiveXObject("ADODB.Stream");
// 最初はテキストモードでUTF-8で書き込む
pre.Type = adTypeText;
pre.Charset = 'UTF-8';
pre.Open();
pre.WriteText(text);
// バイナリモードにするためにPositionを一度0に戻す
// Readするためにはバイナリタイプでないといけない
pre.Position = 0;
pre.Type = adTypeBinary;
// Positionを3にしてから読み込むことで最初の3バイトをスキップする
// つまりBOMをスキップします
pre.Position = 3;
var bin = pre.Read();
pre.Close();

// 読み込んだバイナリデータをバイナリデータとしてファイルに出力する
// ここは一般的な書き方なので説明を省略
var stm = new ActiveXObject("ADODB.Stream");
stm.Type = adTypeBinary;
stm.Open();
stm.Write(bin);
stm.SaveToFile(filename, 2); // force overwrite
stm.Close();
};

一応説明しておくと、一度Streamに対してUTF-8でデータを書き込みます。その後で、バイナリとして最初の3バイト(BOM分)を読み飛ばしてバイナリを読み出します。読み出したバイナリを新しいStreamにバイナリとして食わせてファイルに保存しました。

なんで、こんなに使いづらいAPIになっているんだろう。。。