WSH(JScript)のファイル書み込み・読み込み処理

WSH(JScript)の基本機能をぼちぼちと。BOMまわりの処理がしっかりしたファイル書き込み・書き込み処理です。簡易処理ではありません。記載内は、下記のライブラリを流用しています。

テキストファイルを一括で書き込む

テキストファイルを一括で書き込む// テキストファイル書き込み
// 使用例:_storeText('Hello World.', './test.txt');
// 内容がUTF-8BOMありで「Hello World」のtest.txtをカレントディレクトリに上書きなしで作成する
// 使用例:_storeText('Hello World.', './test.txt', true, 'utf-16', true);
// 内容がUTF-16LEBOMありで「Hello World」のtest.txtをカレントディレクトリに上書きありで作成する
function _storeText(src, path, opt_option, opt_charset, opt_bom) {
  var option  = (opt_option === true)?  2:
                (opt_option === false)? 1:
                (opt_option == null)?   1: opt_option;
  var charset = (opt_charset== null)?   'utf-8': opt_charset;
  var bom     = (opt_bom    == null)?   true: opt_bom;
  var fullpath, skip, bin;
  var ret = true;
  var fs = new ActiveXObject('Scripting.FileSystemObject');

  // 前処理
  charset = charset.toLowerCase();
  skip = {};
  skip['utf-8'] = 3;
  skip['utf-16'] = 2;
  skip['utf-16le'] = 2;
  // UTF-16BEは、スキップ不要(ADODB.StreamがBOMを書き込まないため)
  fullpath = fs.GetAbsolutePathName(path);

  // (存在しない場合)フォルダを作成する
  //_FileUtility_createFileFolder(fullpath);
  {
    var _buffer = [],
        _path = fs.GetAbsolutePathName(fs.GetParentFolderName(fullpath));
    while (_path != '' && !(fs.FolderExists(_path) || fs.FileExists(_path))) {
      _buffer.push(_path);
      _path = fs.GetParentFolderName(_path);
    }
    if (fs.FolderExists(_path)) {
      while ((_path = _buffer.pop()) != null) {
        try {
          fs.CreateFolder(_path);
        } catch (e) {
          break;
        }
      }
    }
  }

  // ファイルに書き込む。
  var sr = new ActiveXObject('ADODB.Stream');
  sr.Type = 2;
  sr.Charset = charset;
  sr.Open();
  sr.WriteText(src);
  if (bom === true && charset == 'utf-16be') {
    // ADODB.Streamは、UTF-16BEのBOMを書き込まないため、自力でBOMを書き込む
    // LEのBOMを確保
    var le = new ActiveXObject('ADODB.Stream');
    le.Type = 2;
    le.Charset = 'utf-16le';
    le.Open();
    le.WriteText('');
    le.Position = 0;
    le.Type = 1;

    // BEのバイナリを確保
    var be = sr;
    be.Position = 0;
    be.Type = 1;
    bin = be.Read();
    be.Close();
    be  = null;
    sr  = null;

    // 再度BOMありを書き込み
    sr = new ActiveXObject('ADODB.Stream');
    sr.Type = 1;
    sr.Open();

    // BOM(LEの1Byteと2Byteが逆)を書き込み
    // BEのバイナリを書き込み
    le.Position = 1;
    sr.Write(le.Read(1));
    le.Position = 0;
    sr.Write(le.Read(1));
    if (bin != null)  sr.Write(bin);

    le.Close();
    le  = null;
  }
  if (bom === false && skip[charset]) {
    // BOMなし書込処理
    var pre = sr;
    pre.Position = 0;
    pre.Type = 1;
    // skipバイト(BOM)を読み飛ばす
    pre.Position = skip[charset];
    bin = pre.Read();
    pre.Close();
    pre = null;
    sr  = null;

    // 再度BOMなしを書き込み
    sr = new ActiveXObject('ADODB.Stream');
    sr.Type = 1;
    sr.Open();
    if (bin != null)  sr.Write(bin);
  }
  try {
    sr.SaveToFile(fullpath, option);
  } catch (e) {       // ADODB.Stream: ファイルへ書き込めませんでした。
    // ファイルあり時、上書きなし
    ret = false;
  }
  sr.Close();
  sr = null;
  return ret;
  // 補足:LineSeparatorプロパティは、全行読み出しのため、無意味
};

テキストファイルを一括で読み込む

テキストファイルを一括で読み込む// テキストファイル読み込み
// 使用例:_loadText('./test.txt');
// カレントディレクトリのtest.txtを文字コード自動認識モードで読み込む
// 使用例:_loadText('./test.txt', 'utf-8');
// カレントディレクトリのtest.txtをUTF-8として読み込む
function _loadText(path, opt_charset) {
  var ret, fullpath, 
      charset = opt_charset,
      skip = false;
  var fs = new ActiveXObject('Scripting.FileSystemObject');

  if (charset == null) { charset = '_autodetect_all'; }
  charset = charset.toLowerCase();

  fullpath = fs.GetAbsolutePathName(path);
  if (!fs.FileExists(fullpath)) {
    // ファイルなし
    return null;
  } else if (fs.GetFile(fullpath).size === 0) {
    // 空ファイル
    return '';
  }

  var sr = new ActiveXObject('ADODB.Stream');
  sr.Type = 2;
  if (charset == '_autodetect_all' || charset == 'utf-16be') {
    // BOMを確認してUTF-8とUTF-16だけ、手動で判定する
    // UTF-16BEは、BOMあり時にBOM削除されないため、手動でスキップする
    var pre = new ActiveXObject('ADODB.Stream');
    pre.Type = 2;
    pre.Charset = 'us-ascii';
    pre.Open();
    pre.LoadFromFile(fullpath);
    var bom = [];
    bom.push(pre.EOS || escape(pre.ReadText(1)));
    bom.push(pre.EOS || escape(pre.ReadText(1)));
    bom.push(pre.EOS || escape(pre.ReadText(1)));
    if (charset == 'utf-16be') {
      if (bom[0] == '%7E' && bom[1]== '%7F') {
        skip = true;
      }
    } else if (bom[0] == 'o'   && bom[1]== '%3B' && bom[2]== '%3F') {
      charset = 'utf-8';
    } else if (bom[0] == '%7F' && bom[1]== '%7E') {
      charset = 'utf-16le';
    } else if (bom[0] == '%7E' && bom[1]== '%7F') {
      charset = 'utf-16be';
      skip = true;
    }
    pre.Close();
    pre = null;
  }
  sr.Charset = charset;

  // ファイルから読み出し
  sr.Open();
  sr.LoadFromFile(fullpath);
  if (skip) {
    // 先頭一文字(BOM)を空読み
    sr.ReadText(1);
    ret = sr.ReadText();
  } else {
    ret = sr.ReadText();
  }

  // 終了処理
  sr.Close();
  sr = null;
  return ret;
};

関連