以下のJSとHTAと+1のファイルの圧縮(LZH) 15KB
.js は単独でも使用できる。
.hta は、.js が必要。もう一つ、.hta が使う 0〜0xff迄の文字を書いたファイルあり。

[ .js ]

// .js 、文字コード(セット)を変換した、別ファイルを作成。
//   目的のファイルかフォルダを、これに落して使う。
//・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
// 設定、
var 設_元コード = ""
        // 元のファイルの文字コードセット。 例、"shift_jis" "iso-2022-jp" "euc-jp" "utf-8" 
        // [HKEY_CLASSES_ROOT\MIME\Database\Charset] のサブキー参照
        //     "_autodetect" というのもあるが、"shift_jis" と "iso-2022-jp" を判断してくれる程らしい。
if(!設_元コード) 設_元コード = "%自判定%"
        // 「設_元コード」が空なら、文字セットを判定してみる。但し使い物にはならず。
        //      "%自判定%" は、関数「文字セット判定」を使うキーワード。
        // ここを消して「設_元コード」を空のままにしておけば、入力ダイアログ出す

var 設_変換後コード = ""
        // 変換後のコードセット指定。 "_autodetect" だと、"shift_jis" に?
        // 空のままにしておけば、入力ダイアログ出す

var 設_変換後改行コード // = "\r\n"
        // ついでに改行コードも変えるとしたら。"\n" "\r\n" などを指定。

var 設_変換後フォルダ = "tmp" 
        // 変換後のファイルを作る場所。(ファイル名は元名を使う)
        // パスでない(ファイル名)なら此処のフォルダ中に。(空なら此処のフォルダ)。".." は使えない。

var 設_バイナリファイル確認パターン = /^[^\xfe\xff]{2}(.|\n)*?[\1-\x06\x0e-\x19\x1c-\x1f]/
        // バイナリファイルと判断して、文字セットの変換を実行しない為のパターン。
        // よく判らないのだが、\0-\x1f の内、テキストにありそうな文字
        //   \0\a\b\t\n\v\f\r eof esc を除いたどれかがあれば、としておく。
        // しかし、これでは、ユニコードをバイナリとしてしまうので、最初の2文字の条件。
        //   バイナリでそれに一致してしまうと困ることになる。
        //   また、最初の2文字(ユニコードのバイト順序指示)がないユニコードも。

//------------------------------------------------
// フォルダを引数に与えた場合の動作
var 設_ファイル名パターン = /\.txt$|\.html?$/i
        // フォルダ中で、作業の対象にするファイルの名前のパターン。
        // 例、拡張子が、xxx → /\.xxx$/i
var 設_フォルダ下降 = false // 真偽 (true|false 、0|1 など)
        // フォルダの中のフォルダの中のファイルにも作業するか?

//------------------------------------------------
// 結果報告を書き出すファイルの設定、(WScriptで実行時のみ、短い場合はダイアログで済ませる事に)
var 設_報告ファイル = "結果報告.tmp.txt";  // パス
        // 報告用ファイルのパス。( \ は、\\ に。/ でもいい)
        //   パスでない(ファイル名)ならこれと同じフォルダに作る。
        //   空なら、クリップボードへ。
var 設_報告ファイル文字セット = "_autodetect"

var 設_エディタ = "" // パス、コマンド
        // 報告ファイルを開くエディタを指定するなら。

// 設定、ここ迄。
//・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
var FS = new ActiveXObject("Scripting.FileSystemObject")
var WS = new ActiveXObject("WScript.Shell")
var IE // "InternetExplorer.Application" 、場合により使う。
var src_STM = new ActiveXObject("ADODB.Stream")
var dest_STM = new ActiveXObject("ADODB.Stream")
var 設_変換後一時フォルダ; // htaで一時的変更の時に使う変数

//・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
// 文字コードセットの判断
// バイナリストリームで開くべきだろうけど、JS のみでは値を得られない為、"iso-8859-1"で開く。
//   但し、0x80-0x9fの間は、元のバイトコードのままではなく、
//     2バイトのユニコードになる(全部ではないが)、(例えば、…†‡‰‘’“”)、(これを書込むと1バイトに戻る)。
//     0xff 以上なら、0x80-0x9f と。

function 文字セット判定(filePath, bchkOnly){ 
        //「bchkOnly」は、バイナリファイルでないかどうかの確認のみ行う。
        // そうでなく文字セット判定で、バイナリファイルと判定したらエラーで返すので、呼出しは try-catch 内で。
        src_STM.Charset = "iso-8859-1" // ascii(Latin-1)のストリームで開く
        src_STM.Open();  src_STM.LoadFromFile(filePath)
        var str = src_STM.ReadText();  src_STM.Close()
        if(設_バイナリファイル確認パターン && 設_バイナリファイル確認パターン.test(str)){  
                if(bchkOnly)return 'バイナリファイル?、中止';
                throw {description:'バイナリファイル?、中止'} // エラー投げる
        }if(bchkOnly) return // バイナリファイル確認のみの場合、ここ迄。
        return 判定試行2(str)  // ← ここで↓の関数を変更。
}///

function 判定試行2(str){ 
        if(/^[\xfe\xff]{2}/.test(str)) return "unicode"
        //if(/\x1b.+\x1b/.test(str)) return "iso-2022-jp"
        if(/\x1b\$.+\x1b\(/.test(str)) return "iso-2022-jp" // /\x1b\$B.+\x1b\(B/
        if(/[\x81-\xfe]|[^\0-\xff]/.test(str)){ 
                //if(/[\xE0-\xEF][\x80-\xBF\u0100-\u3000][\x80-\xBF\u0100-\u3000][\xE0-\xEF]/.test(str)) return "utf-8"
                        // 0x80-0x9f を、大雑把だが、[\u0100-\u3000]
                                // これでは、"shift_jis" "euc-jp" を、"utf-8" としてしまうか。
                if(/[\x81-\x9f]|[^\0-\xff]/.test(str) && !/[\xfd\xfe]/.test(str) ) 
                        return "shift_jis" // "shift_jis" で使わない[\xfd\xfe]が無い事。
                                // [\x8e\x8f] は "euc-jp"にも使われるらしいが。 
                return "euc-jp" //
        }///
        return "iso-8859-1" // "shift_jis"
}///

function 判定試行1(str){ 
        if(/^[\xfe\xff]{2,}/.test(str)) return "unicode"
        var high = false // 0x80 以上のバイトの有無
        for(var i=0, ch; i<str.length; i++){  ch = str.charCodeAt(i)
                if(ch > 0x7f){ if((ch !=0x80 && ch<= 0x9f) || ch>0xff) return "shift_jis" // [\x81-\x9f] がある
                        high = 1; i++  } 
                else if(ch==0x1b) return "iso-2022-jp" // 0x1b(Esc)の有無
        }if(high)return "euc-jp"; return "iso-8859-1" // 
}///

//・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
// 直接の作業部分。文字コードを変換したファイルを作成。
function 文字セットの変換(src_filePath, src_charset, dest_filePath, dest_charset){ 
        // src_filePath 元のファイルパス、src_charset その文字コードセット
        // dest_filePath 変換後の保存先ファイルパス、dest_charset 変換後の文字コードセット指定
        src_STM.Open(); if(src_charset) src_STM.Charset = src_charset // 設定なしは "unicode" で読む
        src_STM.LoadFromFile(src_filePath)
        if(!src_STM.Size){ src_STM.Close(); return '空ファイル?' }
        dest_STM.Open(); if(dest_charset) dest_STM.Charset = dest_charset // 設定なしは "unicode" に変換
        if(設_変換後改行コード) dest_STM.WriteText( 改行の変更( src_STM.ReadText() ) ); // 改行コード変更もする場合。
        else src_STM.CopyTo(dest_STM);  
        src_STM.Close();  var err;  
        try{  dest_STM.SaveToFile(dest_filePath, 2); }catch(e){ err = e.description }// 2 新規作成上書き
        dest_STM.Close();  return err;
}///
function 改行の変更(str){ 
        return str.replace(/\r\n|\n?\r|\n/g, 設_変換後改行コード) // パターンがこれでいいか?
}///

//・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
// 存在しないフォルダを遡って作る
function フォルダ作成(foldPath){ 
        var 合, 名配 = [];  foldPath = foldPath.replace(/\\$/,'');
        while( ! FS.FolderExists(foldPath) ) 
                if(合= foldPath.match(/\\[^\\]+$/)){ 
                        名配.push(合[0]);  foldPath = foldPath.replace(/\\[^\\]+$/,''); }//
                else return( 'フォルダ作成失敗、'+ foldPath +' ?');
        if(名配.length)try{  名配.reverse();  // 名配[n] は "\\名前"
                for(var i=0; i<名配.length; i++) FS.CreateFolder( foldPath += 名配[i] );
        }catch(e){ return 'フォルダ作成失敗、'+ e.description; }
}///
//・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
// 中心。
function 文字コード変換の実行(argA){ 
       
        // フォルダが引数の場合
        function フォルダから作業へ(topFolderPath){ 
                function reflexive_folder(folderPath){
                        pick_file(folderPath)
                        var folderA =[], folders = new Enumerator( FS.GetFolder(folderPath).SubFolders )
                        for (; ! folders.atEnd(); folders.moveNext()) folderA.push( folders.item()+'' )
                        folderA.sort();
                        for(var i=0; i<folderA.length; i++) reflexive_folder( folderA[i] )
                }///
                function pick_file(folderPath){ 
                        var fileA =[], files = new Enumerator( FS.GetFolder(folderPath).Files )
                        for (; ! files.atEnd(); files.moveNext()){ 
                                if(設_ファイル名パターン && ! 設_ファイル名パターン.test(files.item()+'') )continue;
                                fileA.push(files.item()+'')
                        }///
                        if(fileA.length){  fileA.sort(); //for(var i=0; i< fileA.length; i++){ }
                                var relPath = folderPath.replace(topFolderParentPath, '')
                                var newFold = 置場所 + relPath // 「置場所」の末尾には \ あり
                                var str = ファイル配列から作業へ(fileA, newFold)
                                if(str)文 += '['+ relPath +']\n'+ str
                        }///
                }///
                var 文 = '';
                var topFolderParentPath = topFolderPath.replace(/\\[^\\]+\\?$/,'\\')
                        // 各フォルダのパスから、この部分を消す(トップフォルダの名は残した相対パスを出す)為。
                if(設_フォルダ下降) reflexive_folder( topFolderPath )
                else pick_file( topFolderPath )
                return 文;
        }///
       
        // ファイル配列からファイルを取り出して作業(実行)へ送る
        function ファイル配列から作業へ(fileA, 場所){ 
                var str ='', dest_filePath, src_charset = 設_元コード
                for(var i=0, res, flag, errS; i<fileA.length; i++, res=''){ 
                        dest_filePath = 場所.replace(/\\?$/,'\\') + fileA[i].replace(/.+\\/,'')
                        if(判定)try{ src_charset = 文字セット判定(fileA[i])
                        }catch(e){ res = e.description }
                        else res = 文字セット判定(fileA[i], 1)// バイナリファイルでないか、のみ判断
                        if( !変換実行せず && !res && src_charset){ 
                                if( !flag && (errS= フォルダ作成(場所)) )return errS +' 、 '+ 場所 +'\n'; 
                                res = 文字セットの変換(fileA[i], src_charset, dest_filePath, 設_変換後コード)
                        }//
                        str += fileA[i].replace(/.+\\/,'') + (res ?  '   '+res: (判定 ? '   元、'+src_charset: '')) +'\n'
                }/// src_charset と 設_変換後コード が同じになる場合、を考えていない。
                return str
        }/// 
       
        //・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
        if(設_元コード==設_変換後コード){ alert('変換後のコードも同じなので、実行しない'); return; } 
        var res = 引数調べて分ける(argA);  if(!res){ alert(''); return; }
        var fileA = res[0], foldA = res[1]
        var 判定 = 設_元コード=="%自判定%" ? true: false;
        var 置場所 = (設_変換後一時フォルダ ? 設_変換後一時フォルダ: 設_変換後フォルダ);
        置場所 += /\\$/.test(置場所) ? '': '\\';
        var 変換実行せず;
       
        // 実行確認、
        var sConf = '元  、'+ 設_元コード +'\n変換後、'+ 設_変換後コード +'\n\n保存先、'+ 置場所 +'\n';
        if(foldA.length){  
                sConf += '\n'+ (設_フォルダ下降 ?  'フォルダ内部を、降って実行' : '直下のファイルにのみ実行' ) +'\n'
                        + (設_ファイル名パターン ? 'ファイル選択のパターン、  '+設_ファイル名パターン+'\n': '')
                sConf += 'フォルダ、'+ (foldA.length >12 ?  foldA.length+' 個' : '\n'+foldA.join('\n') );
        }///
        if(fileA.length) sConf += '\nファイル、'+ 
                        (fileA.length >12 ?  fileA.length+' 個' : '\n'+fileA.join('\n') ) +'\n';
        //if( 1 != WS.Popup(sConf, 60, '実行確認', 1) )return; 
        var res = WS.Popup( sConf+'\n\n[いいえ]  で、テスト (変換は実行せず)', -1, '実行確認', 3 );  // 三択
        if( !(res==6 || res==7))return; 変換実行せず = (res==7 ? true: false);
       
        // 実行へ
        var report = '';
        if(fileA.length)report = ファイル配列から作業へ(fileA, 置場所)
        for(var i=0, res; i<foldA.length; i++) 
                if( res= フォルダから作業へ(foldA[i]) ) report += res
        // 報告
        if( !report){ alert('該当なし'); return }
        if( !WScript) return report
        if( (res=report.match(/\n/g)) && res.length > 10 ) 報告の書込み(report); 
        else alert('完了\n\n'+ report)// 少ない場合、ダイアログに
}///

function 報告の書込み(文){
        try{ if( ! 設_報告ファイル)throw 0;
                dest_STM.Open();  dest_STM.Charset = 設_報告ファイル文字セット
                dest_STM.WriteText(文);  dest_STM.SaveToFile(設_報告ファイル, 2);
                dest_STM.Close();
        }catch(e){ // 書き込みできなかった時
                if(WScript){  
                        if(!IE){ IE = new ActiveXObject("InternetExplorer.Application"); IE.Navigate("about:blank") }
                        clipboardData = IE.Document.frames.clipboardData  }///
                clipboardData.setData('text', 文);  if(WScript)IE.Quit()
                if(設_報告ファイル || !WScript)alert( (e ? e.description: '') +'\n\n結果は、クリップボードに送った。');
                return
        }/// 結果報告ファイルを開く
        WS.Run( (設_エディタ ? '"'+ 設_エディタ +'" ': '') +'"'+ 設_報告ファイル +'"' )//
}///

function 引数調べて分ける(argA){ 
        var fileA =[], foldA =[], invalidA =[]
        for(var i=0, arg, p; i<argA.length; i++){
                arg = argA[i].replace(/^"(.+)"$/g,'$1');//" HTAの引数の場合
                //if( ! /^\w+:\\|^\\/.test(arg) ) try{ eval(arg); continue }catch(e){ }
                        // ↑コマンドラインから設定、"変数名 = 値" などと。ただ値中の " や \ など厄介。
                if( /\.lnk$/i.test(arg) )// ショートカットの場合。
                        try{ if(p = WS.CreateShortcut(arg).TargetPath)arg = p; else throw 1
                        }catch(e){ invalidA.push(arg) }///
                if(FS.FolderExists(arg)) foldA.push(arg)
                else if(FS.FileExists(arg)) fileA.push(arg)
                else invalidA.push(arg)
        }///
        if(invalidA.length) alert('無効か不明な引数\n\n'+invalidA.join('\n'))
        return [fileA, foldA]
}///
//・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
// 設定の修正と、開始
try{ WScript }catch(e){ WScript =null }// WScript, alert, clipboardData, は宣言せず使用
var cd = WScript ?  WScript.ScriptFullName.replace(/\\[^\\]+$/, '\\')
        : location.pathname.replace(/^[\/]*(.+\\)[^\\]+$/,'$1')
if(設_変換後フォルダ) 設_変換後フォルダ = 設_変換後フォルダ.replace(/[\/]/g,'\\')
if( ! 設_変換後フォルダ || ! /^\\|:/.test(設_変換後フォルダ) ){ 
        if( ! 設_変換後フォルダ)設_変換後フォルダ = '';
        設_変換後フォルダ = cd + 設_変換後フォルダ.replace(/^\.\\/,'')
}///
if(設_報告ファイル) 設_報告ファイル = 設_報告ファイル.replace(/[\/]/g,'\\')
if(設_報告ファイル && ! /^\\|:/.test(設_報告ファイル) ){ 
        設_報告ファイル = cd + 設_報告ファイル.replace(/^\.\\/,'')
}///

function WScriptで実行(){ 
        alert = function(s){ WScript.Echo(s) } 
        if( ! WScript.Arguments.length){ alert('ファイルかフォルダを落す'); return }
        if( !設_元コード || !設_変換後コード){ //alert('設定を'); return 
                IE = new ActiveXObject("InternetExplorer.Application"); IE.Navigate("about:blank")
                var w = IE.Document.frames, s = '例、 shift_jis  iso-2022-jp  euc-jp  utf-8  ';
                if(!設_元コード && (設_元コード = w.prompt('元(現在)の文字セットを\n   '+s, '') ) )
                        設_元コード = 設_元コード.replace(/\0.*/,'')
                if(!設_変換後コード && (設_変換後コード = w.prompt('変換後の文字セットを\n   '+s, 'shift_jis') ) )
                        設_変換後コード = 設_変換後コード.replace(/\0.*/,'')
        }//
        var argA =[]
        for(var i=0; i<WScript.Arguments.length; i++) 
                argA.push( WScript.Arguments(i) )
        文字コード変換の実行(argA)
}if(WScript)WScriptで実行()
//・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
// ここ迄。

[ .hta ]

<head>
<title>文字セット変換 - HTA</title>
<script type="text/javascript" src="文字コード変換.js" id="scr1"></script>
<script type="text/javascript">
// 設定、
var 設_保存後ファイル開く // 真偽、(false 0 "" 未定義 なら偽。以外は真)
        // true でファイル一つを変換や書込みした後に、そのファイルを開く。
        // 但し「設_エディタ」を指定しないとまずい(拡張子により何で開かれるか判らない)。

var 設_バイトファイル = 'bytes'
        // バイナリストリームへの書込み方法判らない為に使う、0〜0xff迄の文字を書いたファイル
設_バイトファイル = location.pathname.replace(/^[\/]*(.+\\)[^\\]+$/,'$1')+設_バイトファイル
        // 同じフォルダに

//・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
var 入力_ファイルパス
function 入力設定の収集(標){ 
        // 標、 1 ファイル内容表示。2 ファイル一つ変換。4 textArea欄文の書込み
        if(標 !=4)設_元コード = select1/**/[ select1/**/.selectedIndex ].value
        if(標 !=1){ 設_変換後コード = select2/**/[ select2/**/.selectedIndex ].value
                var n = select3/**/.selectedIndex
                設_変換後改行コード = n ? (n==1 ? '\r\n': '\n'): null  }// 0 は変更なし
        if(標 < 3){ // 入力欄のファイル1つにのみ実行する場合。
                入力_ファイルパス = txtFilePath/**/.value;  
                if(!入力_ファイルパス) return 'ファイルの入力なし' }//
}///
//・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
function 指定コードで読込んで表示(){ 
        var res; if( res= 入力設定の収集(1) ){ alert(res); return; }
        if(設_元コード=="%バイト%"){  バイト表示(入力_ファイルパス);  return }
        if(設_元コード=="%自判定%")try{ 設_元コード = 文字セット判定(入力_ファイルパス)
        }catch(e){ alert(e.description); return }
        //else if(res= 文字セット判定(入力_ファイルパス, 1)){ alert(res); return;  }
        var str
        try{  src_STM.Charset = 設_元コード;   src_STM.Open();
                src_STM.LoadFromFile(入力_ファイルパス)
                str = src_STM.ReadText();  src_STM.Close(); 
        }catch(e){ if(src_STM.State)src_STM.Close();  alert(e.description); return }//
        ファイル内容の表示(str, 1);  
}///
var byte_STM
function バイト表示(src_filePath){ 
        if( !byte_STM){ byte_STM = new ActiveXObject("ADODB.Stream"); byte_STM.Type = 1; }
        try{  byte_STM.Open();  byte_STM.LoadFromFile(src_filePath);  var str =''; 
                while(!byte_STM.EOS)
                        str += ( '0'+ getByteHex(byte_STM.Read(1)) ).slice(-2)/**/ +' '; // VBS使用
                byte_STM.Close(); 
        }catch(e){ if(byte_STM.State)byte_STM.Close();  alert(e.description); return }//
        str = str.replace(/0D 0A |(0A )?0D |0A /g,'$&\n');   ファイル内容の表示(str)
}///
function ファイル内容の表示(str, escRep){ 
        if(!str){ alert('空?'); return }
        if(escRep) str = str.replace(/[\0-\x1f\x7f-\x9f]/g, // 表示できない(制御)文字は、%hh に。
                        function(c){  if(c=='\n'||c=='\r'||c=='\t')return c;
                                return '%'+ ( '0'+ c.charCodeAt(0).toString(16) ).slice(-2)/**/  } );// 
                                // ↑\x80〜は2バイト文字にされるので指定しても大概は無駄だった("unicode"でない場合)。
        var sInfo = 設_元コード +' :  '+ 入力_ファイルパス.replace(/.+\\/,'')
        infoRes1/**/.innerHTML = sInfo
        //textArea1/**/.value = str; // textArea にも表示してしまうとしたら。
        dispPre.innerHTML = str.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')
                .replace(/\r\n|\n?\r|\n/g, '<br>$&').replace(/ /g, '&nbsp;').replace(/\t/g, '&nbsp;&nbsp;&nbsp;&nbsp;')
                // PRE要素で表示しようと思ったが止め。IEで PRE要素.innerHTML=str とするには、
                //    改行・空白類を通常の要素と同じく BR や &nbsp; に置換する必要ある。
                //    要素.innerHTML='<pre>'+str+'</pre>' とすればそれは不用だが、PRE要素の表示はひどく遅い。
}///
//・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
function ファイル一つを変換へ(){ 
        // 条件・設定の収集、
        var res; if( res= 入力設定の収集(2) ){ alert(res); return; }
        var file = 設_変換後フォルダ + ( /\\$/.test(設_変換後フォルダ) ? '': '\\') 
                        + 入力_ファイルパス.replace(/.+\\/,'') // 保存先ファイルパス
        if(設_元コード=="%自判定%")try{ 設_元コード = 文字セット判定(入力_ファイルパス)
        }catch(e){ alert(e.description); return }
        else if(res= 文字セット判定(入力_ファイルパス, 1)){ alert(res); return;  }
        if( /%/.test(設_元コード) || /%/.test(設_変換後コード) ){ 
                alert("文字セットに、選択されているものは、無効");  return }
        // 確認、
        var s = '元、 '+ 設_元コード +' 、   '+ 入力_ファイルパス.replace(/.*\\/,'') 
                        +'\n後、 '+ 設_変換後コード 
                        +(設_変換後改行コード ?  ' 、  改行 '+設_変換後改行コード.replace(/[\n\r]/g,
                                function(c){ return (c=='\n' ? 'LF':'CR') })+' に'  :'')
                        +' 、    保存先ファイル名は ?'
        if( ! ( file= prompt(s, file) ) )return;  file = file.replace(/\0.*/,'')
        if( !保存場所の確認と処置(file))return
        // 実行へ
        var res = 文字セットの変換(入力_ファイルパス, 設_元コード, file, 設_変換後コード)
        if(res) alert(res); 
        else if(設_保存後ファイル開く)エディタで開く(file)
}///
function 保存場所の確認と処置(filePath){ 
        if(FS.FileExists(filePath) && 
                !confirm('保存先、'+filePath+'\nは、既に存在するが、上書きするか、中止か、')) return
        var err, fold = filePath.replace(/\\[^\\]+$/,'')
        if( ! FS.FolderExists(fold) && (err= フォルダ作成(fold)) ){ alert(err); return; }
        return true;
}///
//・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
// textArea欄の文を、指定のコードでファイルに書込み。
function テキストをファイルに保存(){ 
        var str = textArea1/**/.value;  if( !str ){ alert('欄が空'); return; }
        var res; if( res= 入力設定の収集(4) ){ alert(res); return; }
        var file = 設_変換後フォルダ.replace(/\\$|$/,'\\') + 'tmp.txt'// 保存先ファイルのパス
        if( ! ( file= prompt('保存先のファイルパス・名を入力', file) ) )return;  file = file.replace(/\0.*/,'')
        if(/\\$/.test(file)){ alert('ファイル名を指定のこと'); return; }
        if(設_変換後コード=="%バイト%"){ バイトで書込み(str, file);  return }
        if( !保存場所の確認と処置(file))return
        if(設_変換後改行コード) str = 改行の変更(str)
        try{  dest_STM.Open();  dest_STM.Charset = 設_変換後コード
                dest_STM.WriteText(str);  dest_STM.SaveToFile(file, 2);
                dest_STM.Close();
        }catch(e){ if(dest_STM.State)dest_STM.Close();  alert(e.description); return }//
        if(設_保存後ファイル開く)エディタで開く(file)
}///
function バイトで書込み(str, filePath){ 
        if(!設_バイトファイル){ alert("できない、0〜0xff迄の文字を書いたファイルが必要。"); return }
        // 以下、バイナリストリームへの書込み、方法判らず。
        // テキストストリームだと、例えば、"iso-8859-1" なら、0x80-0x9f が化けるし
        //   "unicode" で書込んで "\0" を削除と考えても、そこでまた同じ問題に会う。
        // 仕方ないので、0〜0xff迄の文字を書いたファイルを用意して
        //     バイナリストリームからバイナリストリームへ書込みことに。→ ※
        if(/[^a-f\d\s]/i.test(str)){ alert('数字、A-F、空白類以外の文字が混ざっている'); return }
        var hexA = str.match(/[a-f0-9]+/ig), codeA =[]
        if( !hexA || !hexA.length){ alert('空'); return; }
        if( !保存場所の確認と処置(filePath))return
        for(var i=0, matchA; i<hexA.length; i++){ 
                matchA = hexA[i].match(/..|./g)
                for(var j=0, n; j<matchA.length; j++)
                        if( !isNaN(n= parseInt('0x'+ matchA[j])) ) codeA.push(n)//codeA.push(getByte(n))
        }///
        try{  if( !byte_STM){ byte_STM = new ActiveXObject("ADODB.Stream"); byte_STM.Type = 1; }
                byte_STM.Open(); 
                //for(var i=0; i< codeA.length; i++) byte_STM.Write( getByte(codeA[i]) )// だめ
                // ↓ 仕方ないので、、※
                var getbyte_STM = new ActiveXObject("ADODB.Stream"); getbyte_STM.Type = 1;
                getbyte_STM.Open();  getbyte_STM.LoadFromFile(設_バイトファイル)
                for(var i=0; i< codeA.length; i++){ 
                        getbyte_STM.Position = codeA[i];   byte_STM.Write( getbyte_STM.Read(1) )
                }getbyte_STM.Close()
                byte_STM.SaveToFile(filePath, 2);  byte_STM.Close(); 
        }catch(e){ if(byte_STM.State)byte_STM.Close(); if(getbyte_STM.State)getbyte_STM.Close();
                alert(e.description); return }//
        if(設_保存後ファイル開く)エディタで開く(filePath)
}///
function エディタで開く(filePath){ 
        WS.Run( (設_エディタ ? '"'+ 設_エディタ +'" ': '') +'"'+ filePath +'"' )//
}///
//・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
function 一括の変換へ(){ 
        // 条件・設定の収集、
        var res; if( res= 入力設定の収集(8) ){ alert(res); return; }
        // 対象のファイル、フォルダ
        var newfileA =[], newfoldA =[], 集 = divArgs/**/.getElementsByTagName('input')
        for(var i=0, 当; i<集.length; i++) 
                if(集[i].checked && (当= 集[i].id.match(/([^\d]+)(\d+)/)) ){ 
                        if(当[1] =='fi') newfileA.push( 引_filePathA[ 当[2] ] )
                        else if(当[1] =='fo') newfoldA.push( 引_foldPathA[ 当[2] ] )
                }///
        var argA = newfileA.concat(newfoldA)
        if( !argA.length){ alert('引数(ファイルかフォルダ)がない'); return }
        if(newfoldA.length){ // フォルダが引数の場合の設定
                var text = filePtn/**/.value, flag, ptn
                if(text){  flag = filePtnflag/**/.value;
                        try{ ptn = new RegExp(text, flag); }catch(e){ throw e; } }///
                設_ファイル名パターン = ptn;
                設_フォルダ下降 = chkReflv/**/.checked
        }///
        // 保存場所の確認・入力、
        var fold = (設_変換後一時フォルダ ? 設_変換後一時フォルダ: 設_変換後フォルダ)
        if( ! (fold= prompt('変換後の保存先フォルダを、', fold) ) ) return
        設_変換後一時フォルダ = fold.replace(/\0.*/,'')
        // 実行と、結果の報告表示
        var resStr = 文字コード変換の実行(argA)
        if(resStr) dispRes.innerHTML = '<pre>'+ resStr.replace(/&/g, '&amp;').replace(/</g,'&lt;') +'</pre>'
}///
//・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
</script><script type="text/vbscript">
Function getByteHex(b): getByteHex = Hex(AscB(b)): End Function
Function getByte(n): getByte = ChrB(n): End Function
</script><script type="text/javascript">
//・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
// 初期表示と引数
var 引_filePathA =[], 引_foldPathA =[] // 引数の配列
onload = function(){ 最初の表示() }///
function 最初の表示(){ 
        引数の表示();
        // セレクト欄のコピー、
        var charset = select1/*.options ?*/[ select1/**/.selectedIndex ].value
        var Ele = select1/**/.cloneNode(true); Ele.id = "select2"
        var 集 = Ele.getElementsByTagName('option') // 変換後用欄には無効なものを削除(idを付けておいた)
        for(var i=0; i<集.length; i++) if(集[i].id)Ele.removeChild(集[i])
        select2P/**/.appendChild(Ele)
        var 集 = Ele.getElementsByTagName('option')// 元の selected がコピーかremoveChildで無効になる為
        for(var i=0; i<集.length; i++) if(集[i].value==charset)集[i].selected = true //(上のfor中では無効)
        // 「お気に入りの整理」コントロールのフォルダ設定
        nsc.setRoot("shell:DesktopFolder")// 
        左引数面の切換え( (引_filePathA.length||引_foldPathA.length ? 0: 1) )
        // 引数にフォルダある場合の設定の表示、// 不用か?
        if(設_ファイル名パターン){ 
                filePtn/**/.value = ( 設_ファイル名パターン ? 設_ファイル名パターン.source : '')
                合 = (設_ファイル名パターン+'').match(/\/([^\/]+)$/)
                filePtnflag/**/.value = (合 && 合[1] ? 合[1]: '')
        }///
        chkReflv/**/.checked = (設_フォルダ下降 ? true: false)
}///
function 引数の表示(){ 
        var argA, res, 文 ='';
        if(window.htaTag && htaTag.commandLine)argA = htaTag.commandLine.match( /".*?"|[^ ]+/g ); 
        if(argA && (argA.shift(), argA.length) && (res= 引数調べて分ける(argA)) ){ 
                引_filePathA = res[0], 引_foldPathA = res[1];  }//
        for(var i=0; i<引_foldPathA.length; i++) 文 += '<div><input type="checkbox" id="fo'
                +i+'" checked> '+ FS.GetFileName(引_foldPathA[i]) +'\\</div>';
        for(var i=0; i<引_filePathA.length; i++)文 += '<div><input type="checkbox" id="fi'
                +i+'" checked> <span class="argf" onclick="ファイル欄へ('+i+')">'
                + FS.GetFileName(引_filePathA[i]) +'</span></div>';
        if(文)divArgs/**/.innerHTML = 文; 
        if(引_filePathA.length) txtFilePath/**/.value = 引_filePathA[0]
        if( !引_foldPathA.length)setfoldSpan/**/.style.display = 'none'
}///
function ファイル欄へ(番){ txtFilePath/**/.value = 引_filePathA[番] }
function 引数の追加(path){ 
        if(!path)return;  var id; // 重複を確かめてない問題あり。
        if(FS.FolderExists(path)){ id = 'fo'+ 引_foldPathA.length;  引_foldPathA.push(path) }//
        else if(FS.FileExists(path)){ id = 'fi'+ 引_filePathA.length;  引_filePathA.push(path) }//
        else{ alert("存在しない"); return }//
        var str = '<div><input type="checkbox" id="'+ id +'" checked> '
                        + path + (/^fo/.test(id) ? '\\':'') +'</div>';
        divArgs/**/.innerHTML += str;
        左引数面の切換え(0)
        if(引_foldPathA.length && setfoldSpan/**/.style.display=='none') setfoldSpan/**/.style.display = ''  
}///
//・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
// 表示に関係のもの
function 操作表示部の切換え(Ele){ 
        if(Ele.className=="switchOn")return
        var idA = ["fileCtrl", "lumpCtrl", "editCtrl"]
        for(var i=0; i<idA.length; i++) 
                if( Ele.id.match(idA[i]) ) Ele.className = 'switchOn',
                        window[ idA[i] ].style.display = ''; 
                else  window[ idA[i]+'Swt' ].className = 'switchOff',
                        window[ idA[i] ].style.display = 'none'; 
        if(/editCtrl/.test(Ele.id)){  editP.style.display = ''
                dispRes.style.display = dispPreP.style.display = 'none';  select1.style.color = 'gray' }//
                //textArea1.value = dispPre.innerHTML;//.replace(/&amp;/g, '&').replace(/&lt;/g,'<')
        else{ editP.style.display = 'none';  select1.style.color = ''
                if(/lumpCtrl/.test(Ele.id)){  
                        dispRes.style.display = '';  dispPreP.style.display = 'none';  左引数面の切換え(0); }//
                else{ dispPreP.style.display = ''; dispRes.style.display = 'none'; }//
        }///
}///
function 左引数面の切換え(番){ 
        divArgs.style.display = 番 ? 'none': '';
        divNsc.style.display = 番 ? '': 'none';
        argAddBtn.style.display = 番 ? '': 'none';
        argNscBtn.style.display = 番 ? '': 'none';
        argTab.className = 番 ? '': 'ltab';
        viewTab.className = 番 ? 'ltab': '';
}///
function テキスト方向の変更(番, 標){ 
        if(標){  dispPre.style.writingMode = (番==1 ? 'tb-rl': '')
                dispPre.style.direction = (番==2 ? 'rtl': '') 
                dispPre.style.unicodeBidi = (番==2 ? 'bidi-override': '');  }//
        else{  textArea1.style.writingMode = (番==1 ? 'tb-rl': '')//'lr-tb' ('rl-tb' はエラー)
                textArea1.style.direction = (番==2 ? 'rtl': '')
                textArea1.style.unicodeBidi = (番==2 ? 'bidi-override': '');
        }// dir や style.direction で、'rtl' を指定しても、右揃えになるだけ(矢印キーが不用に逆になったりも)
        // bdo 要素を使うか、{ unicode-bidi: bidi-override } にすると、方向が変わる。('embed' にしてもだめ)
}///
var strNscSelection; // NameSpace(お気に入りの整理)コントロールの選択されているパスを入れる。
</script>
<hta:application id="htaTag"></hta>
<!--・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・-->
<style type="text/css">
body{ margin:0;  overflow:hidden;  /*line-height:1.8; */
        background-color:window; color:windowtext; }
#dispL, #dispR{ position:absolute; top:0; height:100%;  }/* 左面、右面 */
#dispL{ width:20%;  overflow:auto;  border-right-style:outset;  }/* 左面、リスト */
#dispR{ left:20%; width:80%;   overflow:auto;  } /* 右面 */
// 各面、
#divArgs{ padding:0.5em; padding-top:1em;  }/* 引数表示部分(左面) */
#divArgs div{ padding-left:1.5em; text-indent:-1.5em; word-break:break-all; }
#ctrl0{ white-space:nowrap; /* 操作用部分(右面上部) */
        padding-left:0.5em; padding-top:8px; padding-bottom:4px; }
#dispPre{ /* ファイル内容 表示部分(右面) */
        line-height:1.4; font-family:monospace; padding:0.5em; }

/* フォーム部品(入力欄) */
#select1, #select2{ font-weight:bolder; /*font-size:larger;*/ }/* select欄、文字セット指定 */
.lineText{ font-weight:bolder; font-family:monospace; /* 入力欄  */
        font-size:small;  height:1.6em; line-height:1.6; 
        padding:0; padding-left:4px; padding-right:4px;   }
.lineTextSmall{ font-family:monospace; }/* 入力欄、細字 */
textArea{ line-height:1.2; padding:0.2em; word-break:keep-all;/* 折返して欲しくないのだが方法判らず */
        font-family:monospace; font-size:small;  width:100%;  } /* width:expression(dispR.clientWidth)と
        タグで指定してる(縦書きにした時100%が効かなくなる為)が、何故かここで100%と書いて置かないと少し変に? */

/* ボタン類、など */
.label{ font-size:smaller; }
.btn{  font-weight:bolder; white-space:nowrap; /* ボタン */
        border-style:outset;  border-color:threedlightshadow; cursor:pointer;
        padding-left:2px; padding-top:2px;  vertical-align:20%; }
.argf{ cursor:pointer; }/* 引数表示部分(左面)中のファイル名 */
.switchOn{ background-color:windowtext; color:window; }
.switchOff{ cursor:pointer; background-color:window; color:windowtext; }
.ltab{ background-color:windowtext; color:window; }
</style>
<!--・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・-->
</head><body>
<div id="dispL">
        <div id="" style="text-align:right; margin-top:8px; margin-bottom:0.5em;">
                <span id="argAddBtn" onclick="引数の追加(strNscSelection)" class="btn" style="font-size:smaller;" 
                        title=" 選択されているものを、引数へ追加 ">追加</span>
                <span id="argNscBtn" onclick="var path =strNscSelection; 
                        if(FS.FileExists(path))path=path.replace(/\\[^\\]+$/,'');
                        path=prompt('ルートの変更 、  空ならデスクトップへ',(path ? path:''));
                        if(path) nsc.setRoot(path); else if(path=='')nsc.setRoot('shell:DesktopFolder')" 
                        class="btn" style="font-size:smaller;" title=" ルートの変更 ">R</span>
                <span onclick="左引数面の切換え(0)" id="argTab" class="" style="" 
                        title=" 引数一覧 ">引数</span>
                <span onclick="左引数面の切換え(1)" id="viewTab" class="" style="" 
                        title=" フォルダ・ファイル ツリー ">ビュー</span>
        </div>
        <div id="divArgs" style=""></div>
        <div id="divNsc" style=""><!-- NameSpace(お気に入りの整理)コントロール -->
                <OBJECT id=nsc classid=clsid:55136805-B2DE-11D1-B9F2-00A0C98BC547
                        style="BACKGROUND: window; WIDTH: 100%; HEIGHT: expression(document.body.clientHeight-nsc.offsetTop);">
                        <!--<PARAM NAME="Root" VALUE="shell:DesktopFolder"> ここではだめ? -->
                </OBJECT>
                <SCRIPT for=nsc event="FavoritesSelectionChange(cItems, hItem, strName, strUrl, cVisits, strDate, fAvailableOffline)" defer> 
                        // NameSpaceコントロールの選択項目が変わった時。
                        strNscSelection = strUrl // (ショートカットなら、その行先になる)
                        if(fileCtrl.style.display !='none' && FS.FileExists(strNscSelection) ) 
                                 txtFilePath/**/.value = strNscSelection // ファイルパスを入力する欄へ。
                </SCRIPT> 
        </div>
</div>
<div id="dispR">
        <div id="ctrl0" style="">
                <div style="margin-bottom:1em">
                        <span class="label" title=" 文字セット(Charset)の指定 ">元</span
                        ><select id="select1" style='margin-left:0.3em'><!--<option value="">-->
                                <option value="%自判定%" id="befOnly1">%自判定%
                                <option value="%バイト%">%バイト%
                                <option value="_autodetect">_autodetect
                                <!--<option value="_autodetect_all">_autodetect_all // エラーに? -->
                                <option value="x-user-defined">x-user-defined<!--  -->
                                <option value="shift_jis" selected>shift_jis<option value="iso-2022-jp">iso-2022-jp
                                <option value="euc-jp">euc-jp<option value="unicode">unicode
                                <option value="utf-8">utf-8<option value="utf-7">utf-7
                                <option value="Big5">Big5<!-- 繁体 -->
                                <option value="gb2312">gb2312<!-- "chinese" 簡体 -->
                                <option value="_autodetect_kr">_autodetect_kr<!-- 韓 -->
                                <option value="korean">korean<!-- "ks_c_5601-1987" 韓 -->
                                <option value="iso-8859-1">iso-8859-1<!-- "latin1" 西欧 -->
                                <option value="iso-8859-2">iso-8859-2<!-- "latin2" 中(東)欧 -->
                                <option value="iso-8859-3">iso-8859-3<!-- ラテン 3、エスペラント? -->
                                <option value="iso-8859-4">iso-8859-4<!-- "latin4" バルト(北欧) -->
                                <option value="iso-8859-5">iso-8859-5<!-- "cyrillic" キリル(露) -->
                                <option value="iso-8859-6">iso-8859-6<!-- "arabic" アラビア -->
                                <option value="iso-8859-7">iso-8859-7<!-- "greek" ギリシャ -->
                                <option value="iso-8859-8">iso-8859-8<!-- "hebrew" ヘブライ -->
                                <option value="iso-8859-9">iso-8859-9<!-- "latin5" トルコ -->
                        </select><!-- ↑ 適当に追加などを。[HKEY_CLASSES_ROOT\MIME\Database\Charset] のサブキー参照 -->
                        <!-- 上のselectをコピーして挿入 -->
                        <span class="label" title=" 変換後の Charset の指定 ">→変換後</span
                        ><span id="select2P"></span
                        ><select id="select3" title=" 変換後の改行コード ">
                                <option value="">&nbsp;-<option value="">CRLF<option value="">LF
                        </select> <!>
                        <span onclick="操作表示部の切換え(this)" id="fileCtrlSwt" class="switchOn" style="" 
                                title="">ファイル</span>
                        <span onclick="操作表示部の切換え(this)" id="lumpCtrlSwt" class="switchOff" style="" 
                                title=" 引数の一括処理 ">一括</span>
                        <span onclick="操作表示部の切換え(this)" id="editCtrlSwt" class="switchOff" style="" 
                                title="">編集</span> 
                        <span class="btn" style="font-size:xx-small; " title=" スクリプトファイルの編集 "
                                onclick="location='view-source:'+location.href.replace(/\/[^\/]+$/,'/')+scr1.src">S</span>
                </div>
               
                <div id="fileCtrl" style="">
                        <span class="label">ファイル</span>
                        <input type="text" id="txtFilePath" class="lineTextSmall" size="60" title="">
                        <span onclick="指定コードで読込んで表示();" class="btn" style="" 
                                title=" ファイル内容を、ここに表示 ">表示</span>
                        <span onclick="ファイル一つを変換へ()" class="btn" style="" 
                                title=" 指定のコードで、別ファイルに保存 ">変換</span>
                        <span class="btn" style="font-size:xx-small; "
                                onclick="document.getElementById('fileBox').click();" title=" ファイル参照 ">f..</span>
                        <span style=""> </span><!-- ←これは上の[file..]が位置によって反応しなくなる事、防ぐ為 -->
                        <input type="file" id="fileBox" style="display:none;" 
                                onchange="txtFilePath.value = this.value ? this.value: ''">
                </div>
                <div id="lumpCtrl" style="display:none;">
                        <span id="setfoldSpan">
                                <span title=" フォルダ中のファイルを&#10;   名前で選ぶパターン(正規表現) &#10; 例、拡張子  \.txt$   全て  .* ">
                                        <span class="label">ファイル名パターン 
                                        </span>/<input type="text" id="filePtn" class="lineText" size="30"
                                        >/<input type="text" id="filePtnflag" class="lineTextSmall" size="3" 
                                                title="フラグ、i m g " style="text-align:center; font-weight:bolder;">
                                </span>
                                <input type="checkbox" id="chkReflv" title=" フォルダの中のフォルダも降りて、ファイルに実行 "
                                        ><span class="label">フォルダ下降</span>
                        </span>
                        <span onclick="一括の変換へ()" class="btn" style="" 
                                title=" 引数ファイル群を一括して変換保存 ">変換</span>
                </div>
                <div id="editCtrl" style="display:none; text-align:right; padding-right:1em;">
                        <span class="label">表示</span><select id="" style='margin-left:0.3em'
                                onchange="テキスト方向の変更(this.selectedIndex)">
                                <option value="">横<option value="">縦<option value="">右
                        </select>   
                        <span onclick="テキストをファイルに保存()" class="btn" style="" 
                                title=" テキスト欄の内容をファイルに保存 ">保存</span>
                </div>
        </div>
       
        <div id="dispPreP" style="">
                <div style="padding-left:0.5em; border-bottom-style:outset; border-width:1px;">
                        <span id="infoRes1"></span>   
                        <span class="label">表示</span><select id="" style='margin-left:0.3em'
                                onchange="テキスト方向の変更(this.selectedIndex, 1)">
                                <option value="">横<option value="">縦<option value="">右
                        </select>
                        <input type="checkbox" onclick="dispPre.style.whiteSpace=(this.checked ? '':'nowrap')"
                        ><span class="label">折返し</span>
                </div>
                <div id="dispPre" style="white-space:nowrap;"><bdo id="dispStr"></bdo></div>
        </div>
        <div id="editP" style="display:none;">
                <div id="infoRes2" style=""></div>
                <div><textarea id="textArea1" style="width:expression(dispR.clientWidth);
                        height:expression(document.body.clientHeight-textArea1.offsetTop-2);"></textarea></div>
        </div> <!-- width:100%; では縦にした時、無効になってしまう。↑ -->
        <div id="dispRes" style="display:none; border-top-style:outset; border-width;1px; padding:0.5em"></div>
</div>
<!--・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・-->
<!-- 
表示の不具合で、窓サイズを動かすと、直る場合あり。
左、フォルダ・ファイルビュー(お気に入りの整理のもの)、横スクロールバー出す方法判らない。
        仕方ないので、表示のルートを変える方法で。[R] のボタンを。
unicode でないものを、unicode として読込んで表示するなど、異なる文字セットで、
        ややサイズのあるファイルを [表示] すると、ひどく遅くなるかフリーズすることあり。
-->