複数のファイルをマージする
1.概要
パソコンで色んなデータを扱う場合、複数ファイルの連結(マージ)する作業は比較的多いと思います。
筆者の場合は、Excel VBAやPythonなどで作成したスクレイピングプログラムでWeb上から収集したデータを
CSVなどに出力して加工する場合も多いです。このようなデータを蓄積して1つのファイルに連結(マージ)後、
DB(データベース)を新規作成して、初期インポート用のファイルとして利用しています。
定期的に決まったフォーマットで同じ作業のものは、簡単なバッチファイル(bat)を作って実行させています。
バッチファイルは、WMI(Windows Management Instrumentation)やPower Shellの登場で枯れた技術のように
思われがちですが、企業のIT部門などでは、まだまだ、広く利用されていて現役で活躍しています。
手軽で簡単であり、高速性を求めなければ便利ですね。ただ、会社なとでバッチファイルを他の人に使わせようとした時に、
マージ対象とするファイルやディレクリ―が変更となった場合やマージ後の出力ファイル名が他のシステムと
関連していたりすると、当然変更が必要となるため、その都度、作成者が面倒を見ることになります。
そのような事情から、他の人が使うことを前提とした場合は、GUIで操作画面がある実行形式(exe)のツール
があった方が便利です。今回は、筆者が作成したマージツールを紹介します。
2.ファイルマージツール
2-1.ソースコード 概要で説明しましたが、バッチファイルによる簡単なサンプルを載せておきます。下記のサンプルですが、 必要に応じて、9行目のタイトル名と17行目の処理対象ファイルの拡張子(ワイルドカード)とマージ後の出力ファイル名 を適時修正して利用して下さい。マージ対象ファイルが格納されているディレクトリーは指定していませんので、 追加するか、同一ディレクリ―にバッチファイルを置いて実行させて下さい。どこにでもある簡単なものですみません。 雛形として利用して頂けたらと思います。バッチの命令としては、type命令かcopy命令で同等の処理ができますが、 copy命令の方がやや高速に処理できるようです。
続いて紹介するのが、テキストファイルマージツールです。プログラム言語は、HSP(Hot soup Processer)3.51で
作成しています。HSPとは、20年以上前からサポートが続けられて進化している国産のスクリプト言語です。
最近では、M-1グランプリで優勝したマジカルラブリーの野田クリスタルさんが自作ゲームの開発に利用していることが
話題となり、再び注目されています。HSPに興味がありましたら、下記の公式サイトを覗いてみて下さい。
筆者もちょつとしたツールやアクセサリーなどを開発するのに20年以上前から愛用しています。
プログラミング言語HSP公式サイト : HSPTV
URL : http://hsp.tv/index2.html 下記のリストは、今回紹介するテキストファイルマージツール(tfmarge)のHSPのソースコード(HSPユーザー向け)です。 HSPの開発環境を構築している人は、HSPのスクリプトエディタに読み込み、実行して見て下さい。 HSPの開発環境をインストールしていない場合は、HSP公式サイトから入手して下さい。 マージ処理は、bload命令とbsave命令によるファイルのオフセット値を指定しての読み込みと書き込み による処理のため、比較的高速な処理が実現できています。一応、バイナリーデータもマージ可能です。
2-2.ツールの使い方
テキストファイルマージツール(tfmarge)の使い方です。ツールをダウンロードしたら、任意の場所で解凍して下さい。
ダウンロード
2.ファイルマージツール
2-1.ソースコード 概要で説明しましたが、バッチファイルによる簡単なサンプルを載せておきます。下記のサンプルですが、 必要に応じて、9行目のタイトル名と17行目の処理対象ファイルの拡張子(ワイルドカード)とマージ後の出力ファイル名 を適時修正して利用して下さい。マージ対象ファイルが格納されているディレクトリーは指定していませんので、 追加するか、同一ディレクリ―にバッチファイルを置いて実行させて下さい。どこにでもある簡単なものですみません。 雛形として利用して頂けたらと思います。バッチの命令としては、type命令かcopy命令で同等の処理ができますが、 copy命令の方がやや高速に処理できるようです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | @echo off setlocal cd /d %~dp0 echo. echo. echo *********************************************************** echo. echo CSVファイルのマージ処理 echo. echo. echo *********************************************************** echo. echo. rem ***** マージ開始 ***** copy *.csv > CSVマージ済み.csv echo 処理が完了しました。何かキーを押してください。 echo. pause >nul endlocal exit |
URL : http://hsp.tv/index2.html 下記のリストは、今回紹介するテキストファイルマージツール(tfmarge)のHSPのソースコード(HSPユーザー向け)です。 HSPの開発環境を構築している人は、HSPのスクリプトエディタに読み込み、実行して見て下さい。 HSPの開発環境をインストールしていない場合は、HSP公式サイトから入手して下さい。 マージ処理は、bload命令とbsave命令によるファイルのオフセット値を指定しての読み込みと書き込み による処理のため、比較的高速な処理が実現できています。一応、バイナリーデータもマージ可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 | ;***** テキストファイルマージ (tfmarge.hsp) ***** ;***** 実行ファイル自動作成 **** #packopt type 0 #packopt name "tfmarge" #packopt runtime "hsprt" #packopt hide 1 ;***** notepad命令形式文字列ソート ***** #module #uselib "kernel32.dll" #cfunc lstrcmp "lstrcmpA" int,int #deffunc ntsort var buf,int flag sdim buf2,99999 notesel buf : max=notemax repeat max sdim temp,256 notesel buf : noteget temp,cnt repeat max sdim temp2,256 notesel buf2 : noteget temp2,cnt if temp2= "" : noteadd temp,cnt : break ret=lstrcmp(varptr(temp),varptr(temp2)) if flag=0{ if ret<0 { ;昇順 noteadd temp,cnt break } }else{ if ret>0 { ;降順 noteadd temp,cnt break } } loop loop buf=buf2 return #global #ifndef xdim #uselib "kernel32.dll" #func global VirtualProtect@_xdim "VirtualProtect" var,int,int,var #define global xdim(%1,%2) dim %1,%2: VirtualProtect@_xdim %1,%2*4,$40,x@_xdim #endif #module #uselib "ole32.dll" #func CoTaskMemFree "CoTaskMemFree" int #uselib "shell32.dll" #cfunc SHBrowseForFolder "SHBrowseForFolderA" int #cfunc SHGetPathFromIDList "SHGetPathFromIDListA" int,int #uselib "user32.dll" #func SendMessage "SendMessageA" int,int,int,int #deffunc BrowseFolder str _szTitle, str _defaultfolder szTitle = _szTitle : inifldr = _defaultfolder : sdim retfldr, 260 : xdim fncode, 8 fncode = $08247c83,$8b147501,$ff102444,$68016a30,$00000466,$102474ff,$330450ff,$0010c2c0 hbdata = varptr(inifldr), varptr(SendMessage) BROWSEINFO = hwnd, 0, varptr(retfldr), varptr(szTitle), 3, varptr(fncode), varptr(hbdata), 0 pidl = SHBrowseForFolder(varptr(BROWSEINFO)) fret = SHGetPathFromIDList(pidl,varptr(retfldr)) CoTaskMemFree pidl mref stt,64 : stt = fret return retfldr #global #uselib "comctl32.dll" #func InitCommonControlsEx "InitCommonControlsEx" sptr #cfunc CreateStatusWindow "CreateStatusWindow" int,sptr,int,int #uselib "user32.dll" #func DestroyWindow "DestroyWindow" int #func InvalidateRect "InvalidateRect" int,int,int #func GetWindowRect "GetWindowRect" int,var #define VER_TFAPPRI 1.0 #define MAXPATH 260 #define CB_GETLBTEXT $00000148 #define EM_SETMARGINS $000000D3 #define EC_LEFTMARGIN $00000001 #define EC_RIGHTMARGIN $00000002 #define SB_SETTEXT $00000401 #define ctype MAKELONG(%1,%2) (%1&$ffff|(%2<<16)) sdim instdir, MAXPATH sdim genename,MAXPATH sdim Folder, MAXPATH sdim tmpstr,64 sdim s,1024*5 sdim buf sdim cb sdim temp sdim outname,48 ;***** 起動ディレクトリ取得 ***** if hspstat&1=0 { instdir=dirinfo(1)+ "¥¥" : chdir dirinfo(1) } else { instdir=dirinfo(0)+ "¥¥" } ;***** GUI画面作成 ***** screen 0,580,200,0 sysfont 17 : syscolor 8 BarName= "テキストファイルマージ Ver" +strf( "%.1f" ,VER_TFAPPRI)+ " (tfmarge)" title BarName font "Meiryo UI" ,12,0 : objmode 2 color 0,0,0 : pos 11,15 : mes "対象先" pos 55,11 : input Folder,400,20 sendmsg objinfo(0,2), EM_SETMARGINS, EC_LEFTMARGIN|EC_RIGHTMARGIN,MAKELONG(2,0) objsize 46,24 : pos 459,8: button "参照" , *dirset wcard= "*.*¥n*.txt¥n*.dat¥n*.csv¥n*.htm¥n*.html¥n*.css¥n*.xml¥n*.log" pos 11,43 : mes "拡張子" font "Meiryo UI" ,14,0 : objmode 2 n=1 : objsize 80,24 : pos 55,38: combox n,120,wcard font "Meiryo UI" ,12,0 : objmode 2 pos 150,43 : mes "出力ファイル名" font "Meiryo UI" ,12,0 : objmode 2 pos 235,40 : input outname,220,20 sendmsg objinfo(3,2), EM_SETMARGINS, EC_LEFTMARGIN|EC_RIGHTMARGIN,MAKELONG(2,0) objsize 46,24 : pos 459,37: button gosub "自動" , *autoname objsize 60,50 : pos 510,11: button "マージ" , *marge ;***** StatusBar object setting ***** gosub *statusGen gosub *statusMsg gosub *statusstring gsel 0,1 ;***** 割込み処理 ***** onexit goto *owari onclick gosub *msgclr stop *dirset ;***** フォルダ選択ダイアログを起動 ***** BrowseFolder "フォルダを選択してください" , dir_cur if stat { Folder = refstr+ "¥¥" } objprm 0,Folder stop *autoname ;***** 日付時刻をファイル名と仮設定する ***** outname =str(gettime(0)) outname+=strf( "%02d" ,gettime(1)) outname+=strf( "%02d" ,gettime(3)) outname+=strf( "%02d" ,gettime(4)) outname+=strf( "%02d" ,gettime(5)) outname+=strf( "%02d" ,gettime(6)) ;コンボボックスの選択文字列を取得(拡張子) sendmsg objinfo(2,2),CB_GETLBTEXT,n,varptr(temp) p=strlen(temp) outname+=strmid(temp,1,p-1) objprm 3,outname return *statusMsg ;***** ステータスバー初期メッセージ ***** String = " ファイルマージ(連結)する対象先ディレクトリを指定して下さい。" return *statusGen ;***** ステータスバーを作成 ***** InitCommonControlsEx icx : String = "" stshwnd=CreateStatusWindow($50000803, String ,hwnd,0) InvalidateRect stshwnd,0,1 dim rc,4 : GetWindowRect stshwnd,rc : sh = rc(3)-rc(1) return *statusstring ;***** ステータスバーに文字列を設定 ***** sendmsg stshwnd,SB_SETTEXT,0,varptr( String ) return *msgclr ;***** メッセージクリア ***** color 255,255,255 : boxf 19,109,320,122 : color 0,0,0 return *marge ;***** マージ処理開始 ***** gosub *msgclr if Folder= "" { dialog "ファイルマージする対象フォルダを指定して下さい。" ,0 stop } chdir Folder ; 指定ディレクトリのファイル名のみを取得 sendmsg objinfo(2,2),CB_GETLBTEXT,n,varptr(cb) dirlist s,cb,1 : num=stat ; ファイル名を五十音別に昇順ソート ntsort s, 0 ; 出力ファイルの空の実体を作成する notesel buf if outname= "" { String = " 出力ファイル名が省略されたので、日付時刻のファイル名を仮設定しました。" gosub *statusstring gosub *autoname } genename=Folder+outname notesave genename notesel s ; 1個目のファイルをマージする noteget tmpstr,0 exist Folder+tmpstr if strsize=-1 { dialog "指定したディレクトリにはファイルがありません。" ,0 : stop } sdim filebuf,strsize bload Folder+tmpstr,filebuf,strsize bsave genename,filebuf,strsize,0 offset=strsize ; n個目のファイルをマージする repeat num,1 noteget tmpstr,cnt exist Folder+tmpstr : sdim filebuf,strsize if strsize=-1 : break bload Folder+tmpstr,filebuf,strsize bsave genename,filebuf,strsize,offset fsize =strsize : offset+=fsize loop exist genename pos 20,110 : mes "ファイルのマージ処理が完了しました。" + " " +strsize+ "byte" outname = "" gosub *statusMsg gosub *statusstring stop *owari ;***** 終了処理 ***** onexit 0 DestroyWindow stshwnd end |
-
(1)tfmarge.exeをダブルクリックして起動させます。
-
(2)連結(マージ)対象のファイルが格納されているディレクリ―を参照ボタンをクリックして
選択します。
(3)拡張子をプルダウンよりクリックして選択します。
(4)マージ後の出力ファイル名(拡張子含む)を入力します。自動ボタンをクリックすると
日付時刻形式のファイル名が作成されます。※省略時も同じです。
(5)マージボタンをクリックしてマージ処理を実行します。
-
(5)マージ対象ファイル数や容量にも依りますが、比較的高速に処理されます。
完了後、tfmarge.exeを閉じて下さい。
ダウンロード
コメント
コメントを投稿