ADODB.Streamなしに、WSHでバイナリを出力する

方法を思いつきました。
いまだ、この手のワードで検索されるので、書いておきます。
ただ、ニーズがあるかどうか不明なので、完成はさせてません。
しかも縛りが多いし。

制約

  • 0x80〜0xFFまでのバイナリファイルが必要(ホントはもう少し少なくても良いが)
    • これは、127個の1バイトのファイルが必要ということ
  • WScript.ShellとScripting.FileSystemObjectに依存
  • JScriptのみ(VBScriptでは不可、、、な気がする)

ヒント

  • FileSystemObjectを使うと、ASCIIでなら、0〜127まで出力可能
  • JScriptでFileSystemObjectを使うと、Unicodeでなら、0〜65535まで出力可能。
    ただしこれは2バイトづつ。BOMが付く
    VBScriptだと上手く出力できない、、、。
  • コマンドプロンプトのcopyはバイナリの結合が可能
    (「copy /b b1 + b2 b」で、b1とb2を結合してbに書き出せる)

方法

  1. 最初の2バイトは、ASCIIモードで出力する
    1. 最初の2バイトに、ASCII範囲外がある場合は、WScript.Shellで1バイトファイルを結合して作成
  2. 残りは、Unicodeモードで2バイトづつ出力する
  3. 最後が2バイトにならない場合(全体が奇数バイトの場合)、ASCIIで出力する
    1. こちらも、ASCII範囲外の場合は、copyでの結合を行う

今回の検討に使用したコード

var ForReading = 1;
var ForWriting = 2;
var ForAppending = 8;
var TristateUseDefault = -2;	// システムデフォルトでファイルを開く
var TristateTrue = -1;			// ファイルをUnicodeファイルとして開く
var TristateFalse = 0;			// ファイルをASCIIファイルとして開く

var OutFile = "binOut.out";

	var OutStream, res;
	var WshShell = WScript.CreateObject("WScript.Shell");
	var fso = new ActiveXObject("Scripting.FileSystemObject");
	var scriptPath = WScript.ScriptFullName.substr(0, WScript.ScriptFullName.length - WScript.ScriptName.length);
	WScript.Echo(scriptPath);

	res = WshShell.Run("cmd /c copy /b binOut80.bin + binOut81.bin " + OutFile, 0, true);

	OutStream = fso.OpenTextFile(OutFile, ForAppending, true, TristateFalse);
	for(i = 0; i < 128; i++) {
		OutStream.Write(String.fromCharCode(i));
	}
	OutStream.Close();
	OutStream = fso.OpenTextFile(OutFile, ForAppending, true, TristateTrue);
	for(i = 0; i < 65536; i++) {
		OutStream.Write(String.fromCharCode(i));
	}
	OutStream.Close();


WScript.Echo("Fin!");
  • binOut80.bin は、0x80が書かれたファイル。binOut81.binは、0x81。


ニーズがあれば、作成しますよ。
ニーズがあればね。
、、、ってか、「copy /b」を使う時点で、256個のバイナリがあれば出来るって話も、、、。


ついでに、前検討したWSHBase64エンコード・デコードにトラックバックしときましょ。
WSHでBase64
JScriptでBase64デコード