気づいてしまった、、、。
追記(2011/09/29)
ただのBase64変換で良く、使うオブジェクトに制限がなければ、お手軽版があります。
WSHでバイナリー・テキスト相互変換(Base64変換) - じゅんじゅんのきまぐれ
いえ、最近ごそごそやってる、Base64デコードスクリプト。
前回の検討はこちら
バイナリ出力を、テキスト形式で行うとNGな理由が、VBScriptの文字の取り扱いにあるのでは?
と、閃いてしまったのです。
で、試しにやってみました。
JScript版。
// テキスト→バイナリ // f2t.vbsが変換したテキストファイルをバイナリに戻す // Cr / Lf / (space) は無視しますので、変換文字には使えません var TransTbl, PadChar, SecondTbl; var sp = new Array(6, 4, 2, 0); TransTbl = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; SecondTbl = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; PadChar = "="; var adTypeBinary = 1; var adTypeText = 2; var Non = 256; var TblLen = 64; var ForReading = 1; var ForWriting = 2; var ForAppending = 8; var TristateUseDefault = -2; // システムデフォルトでファイルを開く var TristateTrue = -1; // ファイルをUnicodeファイルとして開く var TristateFalse = 0; // ファイルをASCIIファイルとして開く var LogStream = null; /********************************************************** ログ出力 **********************************************************/ function LogWrite(msg) { if(LogStream != null) { LogStream.Write(msg); } } /********************************************************** 1Byteを二つに分割する **********************************************************/ function SplitByte(inData, split) { var s = Math.pow(2, split); inData[1] = Math.floor(inData[0] / s); inData[2] = inData[0] % s; } var mDecodeIndex = 0, mDecode = new Array(4); /********************************************************** decode **********************************************************/ var ret = new Array(3); var spBuf = new Array(new Array(3), new Array(3), new Array(3), new Array(3)); function decode(target) { // 内部バッファに蓄える if(target.charCodeAt(0) != 10 && target.charCodeAt(0) != 13 && target.charCodeAt(0) != 32) { mDecode[mDecodeIndex] = target; mDecodeIndex++; } if(mDecodeIndex < 4) { return null; } mDecodeIndex = 0 var inBuf, i, outBuf; // 4文字読込み、それぞれを数字にする // 上位Bit,下位Bitに分解する for(i = 0; i < 4; i++) { inBuf = mDecode[i]; LogWrite(inBuf); spBuf[i][0] = TransTbl.indexOf(inBuf); if(spBuf[i][0] == -1) { spBuf[i][0] = SecondTbl.indexOf(inBuf); } if(spBuf[i][0] == -1) { spBuf[i][1] = 0; spBuf[i][2] = 0; } else { SplitByte(spBuf[i], sp[i]); } } for(i = 0; i < 4; i++) { LogWrite(" " + spBuf[i][0] + "=" + spBuf[i][1] + ":" + spBuf[i][2]); } // 合成して出力する for(i = 0; i < 3; i++) { if(spBuf[i+1][0] < TblLen) { ret[i] = spBuf[i][2] * Math.pow(2, (8 - sp[i])) + spBuf[i+1][1] } else { ret[i] = Non; } LogWrite(" " + ret[i]); } LogWrite("\r\n"); return ret; } /********************************************************** main **********************************************************/ function main(target, outFile, table, pad, log) { var fso, InStream, OutStream; // Stream オブジェクト の作成 fso = new ActiveXObject("Scripting.FileSystemObject"); // 変換テーブル用文字列を読込む(指定がない場合は、デフォルト) if(table.length > 0) { InStream = fso.OpenTextFile(table, ForReading, false, TristateUseDefault); TransTbl = InStream.Read(TblLen); InStream.Close(); } // パディングが指定されている場合は、それを使う if(pad.length > 0) { PadChar = pad; } TransTbl = TransTbl + PadChar; SecondTbl = SecondTbl + PadChar; InStream = fso.OpenTextFile(target, ForReading, false, TristateUseDefault); OutStream = new ActiveXObject("ADODB.Stream"); OutStream.Type = adTypeText; OutStream.charset = "iso-8859-1"; OutStream.Open(); if(log.length > 0) { LogStream = fso.OpenTextFile(log, ForAppending, true, TristateUseDefault); } else { LogStream = null; } // 対象ファイルが終わるまで以下の処理を行う var inBuf, buf, i, trans while(!InStream.AtEndOfStream) { // 4文字読込み、それぞれを数字にする inBuf = InStream.Read(1); // 合成して出力する buf = decode(inBuf); if(buf != null) { for(i = 0; i < 3; i++) { if(buf[i] < Non) { OutStream.WriteText(String.fromCharCode(buf[i])); } } } } InStream.Close(); OutStream.SaveToFile(outFile, 2); OutStream.Flush(); OutStream.Close(); if(LogStream != null) { LogStream.Close(); } InStream = null; OutStream = null; LogStream = null; } var arg = new Array(5), i; for(i = 0; i < 5; i++) { if(WScript.Arguments.length > i) { arg[i] = WScript.Arguments.item(i); } else { arg[i] = ""; } } main(arg[0], arg[1], arg[2], arg[3], arg[4]); WScript.Echo("Fin!");
JScriptだと、こういう方法もあるのですねぇ。
ま、VBScriptの場合は、転載許可を頂いたクラスのお世話になるしかなさそうです。
ちなみに、「ADODB.Stream」は使うしかないようです、、、。
FileSystemObjectにS-JISのリーダバイトあたりを出力させようとすると、怒られます。
「Scripting.FileSystemObject」は「ADODB.Stream」で代用が利きますが、「ADODB.Stream」は任意の出力ができなさそうなため、ロガーとしてイマイチなのです、、、。
コマンドライン専用を想定するならば、ログは標準出力、という手もあるから、依存が少し減らせるけど。
いや、どちらかと言えば「ADODB.Stream」を減らしたいので、私には意味がないかも。
書いてて気づいた。
これって、Stream系クラスにすべきですね。
そうすれば、取り扱いも概念的に楽になるし。
Base64EncoderStreamとBase64DecoderStreamかな。