001/* 002 * Copyright (c) 2009 The openGion Project. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 013 * either express or implied. See the License for the specific language 014 * governing permissions and limitations under the License. 015 */ 016package org.opengion.fukurou.util; 017 018import org.opengion.fukurou.system.OgRuntimeException ; // 6.4.2.0 (2016/01/29) 019import java.io.BufferedInputStream; 020import java.io.BufferedOutputStream; 021import java.io.BufferedReader; 022import java.io.BufferedWriter; 023import java.io.File; 024import java.io.FileFilter; // 7.0.1.4 (2018/11/26) 025import java.io.InputStream; 026import java.io.FileInputStream; 027import java.io.InputStreamReader; // 5.10.9.0 (2019/03/01) 028import java.io.FileNotFoundException; 029import java.io.FileOutputStream; 030import java.io.IOException; 031import java.io.OutputStream; 032import java.io.OutputStreamWriter; 033import java.io.PrintWriter; 034import java.io.UnsupportedEncodingException; 035import java.io.Writer; 036import java.util.Collections; 037import java.util.List; 038 039import java.nio.channels.FileChannel; 040import java.nio.file.Files; // 6.2.0.0 (2015/02/27) 041import java.nio.charset.Charset; // 6.2.0.0 (2015/02/27) 042import java.nio.file.StandardCopyOption; // 5.10.9.0 (2019/03/01) 043 044import org.opengion.fukurou.system.HybsConst; // 6.4.5.2 (2016/05/06) 045import static org.opengion.fukurou.system.HybsConst.CR; // 6.1.0.0 (2014/12/26) refactoring 046import org.opengion.fukurou.system.Closer; // 6.4.2.0 (2016/01/29) package変更 fukurou.util → fukurou.system 047import org.opengion.fukurou.system.LogWriter; // 6.4.2.0 (2016/01/29) package変更 fukurou.util → fukurou.system 048import org.opengion.fukurou.system.ThrowUtil; // 6.4.2.0 (2016/01/29) package変更 fukurou.util → fukurou.system 049import org.opengion.fukurou.model.FileOperation; // 5.10.9.0 (2019/03/01) 050import org.opengion.fukurou.model.FileOperationFactory; // 5.10.9.0 (2019/03/01) 051 052/** 053 * FileUtil.java は、共通的に使用される File関連メソッドを集約した、クラスです。 054 * 055 * 全変数は、public static final 宣言されており、全メソッドは、public static synchronized 宣言されています。 056 * 057 * @og.rev 5.9.10.0 (2019/03/01) クラウドストレージ対応を追加 058 * 059 * @og.group ユーティリティ 060 * 061 * @version 4.0 062 * @author Kazuhiko Hasegawa 063 * @since JDK5.0, 064 */ 065public final class FileUtil { 066 private static final NonClosePrintWriter OUT_WRITER = new NonClosePrintWriter( System.out ); // 6.4.1.1 (2016/01/16) outWriter → OUT_WRITER refactoring 067 private static final NonClosePrintWriter ERR_WRITER = new NonClosePrintWriter( System.err ); // 6.4.1.1 (2016/01/16) errWriter → ERR_WRITER refactoring 068 069 /** 5.6.1.2 (2013/02/22) UNIX系のファイル名を表すセパレータ文字 */ 070 071 /** 5.6.1.2 (2013/02/22) Windwos系のファイル名を表すセパレータ文字 */ 072 073 /** 5.6.1.2 (2013/02/22) ファイルの拡張子の区切りを表す文字 */ 074 public static final char EXTENSION_SEPARATOR = '.'; 075 076 private static final byte B_CR = (byte)0x0d ; // '\r' 077 private static final byte B_LF = (byte)0x0a ; // '\n' 078 private static final int BUFSIZE = 8192 ; // 5.1.6.0 (2010/05/01) 079 080 /** 081 * すべてが staticメソッドなので、コンストラクタを呼び出さなくしておきます。 082 * 083 */ 084 private FileUtil() {} 085 086 /** 087 * Fileオブジェクトとエンコードより PrintWriterオブジェクトを作成します。 088 * 089 * @param file 出力するファイルオブジェクト 090 * @param encode ファイルのエンコード 091 * 092 * @return PrintWriterオブジェクト 093 * @throws RuntimeException 何らかのエラーが発生した場合 094 * @og.rtnNotNull 095 */ 096 public static PrintWriter getPrintWriter( final File file,final String encode ) { 097 return getPrintWriter( file,encode,false ); 098 } 099 100 /** 101 * Fileオブジェクトとエンコードより PrintWriterオブジェクトを作成します。 102 * 103 * @param file 出力するファイルオブジェクト 104 * @param encode ファイルのエンコード 105 * @param append ファイルを追加モード(true)にするかどうか 106 * 107 * @return PrintWriterオブジェクト 108 * @throws RuntimeException 何らかのエラーが発生した場合 109 * @og.rtnNotNull 110 */ 111 public static PrintWriter getPrintWriter( final File file,final String encode,final boolean append ) { 112 final PrintWriter writer ; 113 114 try { 115 writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter( 116 new FileOutputStream(file,append) ,encode ))); 117 } 118 catch( final UnsupportedEncodingException ex ) { 119 final String errMsg = "指定されたエンコーディングがサポートされていません。" + CR 120 + ex.getMessage() + CR 121 + "File=[" + file + " , encode=[" + encode + "]" ; 122 throw new OgRuntimeException( errMsg,ex ); 123 } 124 catch( final FileNotFoundException ex ) { // 3.6.1.0 (2005/01/05) 125 final String errMsg = "ファイル名がオープン出来ませんでした。" + CR 126 + ex.getMessage() + CR 127 + "File=[" + file + " , encode=[" + encode + "]" ; 128 throw new OgRuntimeException( errMsg,ex ); 129 } 130 131 return writer ; 132 } 133 134 /** 135 * ファイル名より、PrintWriterオブジェクトを作成する簡易メソッドです。 136 * 137 * これは、ファイル名は、フルパスで、追加モードで、UTF-8 エンコードの 138 * ログファイルを出力する場合に使用します。 139 * また、ファイル名に、"System.out" と、"System.err" を指定できます。 140 * その場合は、標準出力、または、標準エラー出力に出力されます。 141 * "System.out" と、"System.err" を指定した場合は、NonClosePrintWriter 142 * オブジェクトが返されます。これは、close() 処理が呼ばれても、何もしない 143 * クラスです。また、常に内部キャッシュの同じオブジェクトが返されます。 144 * 145 * @param file 出力するファイル名 146 * 147 * @return PrintWriterオブジェクト 148 * @throws RuntimeException 何らかのエラーが発生した場合 149 * @throws IllegalArgumentException ファイル名が null の場合 150 */ 151 public static PrintWriter getLogWriter( final String file ) { 152 if( file == null ) { 153 final String errMsg = "ファイル名に、null は指定できません。"; 154 throw new IllegalArgumentException( errMsg ); 155 } 156 157 final PrintWriter writer ; 158 if( "System.out".equalsIgnoreCase( file ) ) { 159 writer = OUT_WRITER ; 160 } 161 else if( "System.err".equalsIgnoreCase( file ) ) { 162 writer = ERR_WRITER ; 163 } 164 else { 165 writer = getPrintWriter( new File( file ),"UTF-8",true ); 166 } 167 168 return writer ; 169 } 170 171 /** 172 * OutputStreamとエンコードより PrintWriterオブジェクトを作成します。 173 * 174 * @og.rev 5.5.2.0 (2012/05/01) 新規追加 175 * 176 * @param os 利用するOutputStream 177 * @param encode ファイルのエンコード 178 * 179 * @return PrintWriterオブジェクト 180 * @throws RuntimeException 何らかのエラーが発生した場合 181 */ 182 public static PrintWriter getPrintWriter( final OutputStream os,final String encode ) { 183 final PrintWriter writer ; 184 185 try { 186 writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter( os ,encode ))); 187 } 188 catch( final UnsupportedEncodingException ex ) { 189 final String errMsg = "指定されたエンコーディングがサポートされていません。" + CR 190 + ex.getMessage() + CR 191 + "encode=[" + encode + "]" ; 192 throw new OgRuntimeException( errMsg,ex ); 193 } 194 return writer ; 195 } 196 197 /** 198 * PrintWriter を継承した、JspWriterなどの Writer 用のクラスを定義します。 199 * 200 * 例えば、JspWriterなどの JSP/Servlet等のフレームワークで使用される 201 * Writer では、flush や close 処理は、フレームワーク内で行われます。 202 * その場合、通常のファイルと同じ用に、flush や close をアプリケーション側で 203 * 行うと、内部処理的に不整合が発生したり、最悪の場合エラーになります。 204 * このクラスは、NonFlushPrintWriter クラスのオブジェクトを返します。 205 * これは、通常の、new PrintWriter( Writer ) で、求めるのと、ほとんど同様の 206 * 処理を行いますが、close() と flush() メソッドが呼ばれても、何もしません。 207 * 208 * @param writer 出力するWriteオブジェクト(NonFlushPrintWriterクラス) 209 * 210 * @return PrintWriterオブジェクト 211 * @og.rtnNotNull 212 */ 213 public static PrintWriter getNonFlushPrintWriter( final Writer writer ) { 214 return new NonFlushPrintWriter( writer ); 215 } 216 217 /** 218 * Fileオブジェクトとエンコードより BufferedReaderオブジェクトを作成します。 219 * 220 * これは、java 1.7 以降でしか使えませんが、FilesとPaths を使用した BufferedReader 221 * オブジェクトを返します。 222 * encode は、java.nio.charset.Charset になる為、従来のコードと異なるかも知れませんが、 223 * 日本語関係の判定をより正確に行う事が可能になります。(Windows-31J と UTF-8の判別など) 224 * 225 * @og.rev 6.2.0.0 (2015/02/27) java.nio.file.Files と、Paths を使用するように変更 226 * @og.rev 5.10.9.0 (2019/3/1) FileOperationの処理を追加(クラウドストレージ対応) 227 * 228 * @param file 入力するファイルオブジェクト 229 * @param encode ファイルのエンコード(java.nio.charset.Charset) 230 * 231 * @return BufferedReaderオブジェクト 232 * @throws RuntimeException 何らかのエラーが発生した場合 233 * @og.rtnNotNull 234 */ 235 public static BufferedReader getBufferedReader( final File file,final String encode ) { 236 final BufferedReader reader ; 237 238 try { 239 if( file instanceof FileOperation ) { 240 final FileOperation fileOperation = (FileOperation)file; 241 reader = new BufferedReader(new InputStreamReader(fileOperation.read(), encode)); 242 }else { 243 reader = Files.newBufferedReader( file.toPath() , Charset.forName( encode ) ); 244 } 245 246// reader = Files.newBufferedReader( file.toPath() , Charset.forName( encode ) ); 247 } 248 catch( final IOException ex ) { 249 final String errMsg = "ファイルのオープン中に入出力エラーが発生しました。" + CR 250 + ex.getMessage() + CR 251 + "File=[" + file + "] , encode=[" + encode + "]" ; 252 throw new OgRuntimeException( errMsg,ex ); 253 } 254 catch( final RuntimeException ex ) { 255 final String errMsg = "指定された文字セットが不正か、現在のJava仮想マシンでは利用できません。" + CR 256 + ex.getMessage() + CR 257 + "File=[" + file + "] , encode=[" + encode + "]" ; 258 throw new OgRuntimeException( errMsg,ex ); 259 } 260 261 return reader ; 262 } 263 264 /** 265 * 指定のファイル名が、実際に存在しているかどうかをチェックします。 266 * 存在しない場合は、2秒毎に、3回確認します。 267 * それでも存在しない場合は、エラーを返します。 268 * return されるFileオブジェクトは、正規の形式(CanonicalFile)です。 269 * 270 * @param dir フォルダ名 271 * @param filename ファイル名 272 * 273 * @return 存在チェック(なければ null/あれば、CanonicalFile) 274 */ 275 public static File checkFile( final String dir, final String filename ) { 276 return checkFile( dir,filename,3 ); 277 } 278 279 /** 280 * 指定のファイル名が、実際に存在しているかどうかをチェックします。 281 * 存在しない場合は、2秒毎に、指定の回数分確認します。 282 * それでも存在しない場合は、エラーを返します。 283 * return されるFileオブジェクトは、正規の形式(CanonicalFile)です。 284 * 285 * @param dir フォルダ名 286 * @param filename ファイル名 287 * @param count 回数指定 288 * 289 * @return 存在チェック(なければ null/あれば、CanonicalFile) 290 */ 291 public static File checkFile( final String dir, final String filename,final int count ) { 292 File file = null; 293 294 int cnt = count; 295 while( cnt > 0 ) { 296 file = new File( dir,filename ); 297 if( file.exists() ) { break; } 298 else { 299 if( cnt == 1 ) { return null; } // 残り1回の場合は、2秒待機せずに即抜ける。 300 try { Thread.sleep( 2000 ); } // 2秒待機 301 catch( final InterruptedException ex ) { 302 System.out.println( "InterruptedException" ); 303 } 304 System.out.println(); 305 System.out.print( "CHECK File Error! CNT=" + cnt ); 306 System.out.print( " File=" + file.getAbsolutePath() ); 307 } 308 cnt--; 309 } 310 311 // ファイルの正式パス名の取得 312 try { 313 return file.getCanonicalFile() ; 314 } 315 catch( final IOException ex ) { 316 final String errMsg = "ファイルの正式パス名が取得できません。[" + file.getAbsolutePath() + "]"; 317 throw new OgRuntimeException( errMsg,ex ); 318 } 319 } 320 321 /** 322 * ファイルのバイナリコピーを行います。 323 * 324 * copy( File,File,false ) を呼び出します。 325 * 326 * @og.rev 5.1.6.0 (2010/05/01) 戻り値に、true/false 指定します。 327 * 328 * @param fromFile コピー元ファイル名 329 * @param toFile コピー先ファイル名 330 * 331 * @return バイナリコピーが正常に終了したかどうか[true:成功/false:失敗] 332 * @see #copy( File,File,boolean ) 333 */ 334 public static boolean copy( final String fromFile,final String toFile ) { 335 return copy( new File( fromFile ), new File( toFile ), false ); 336 } 337 338 /** 339 * ファイルのバイナリコピーを行います。 340 * 341 * copy( File,File,boolean ) を呼び出します。 342 * 第3引数の、keepTimeStamp=true で、コピー元のファイルのタイムスタンプを、 343 * コピー先にもセットします。 344 * 345 * @og.rev 5.1.6.0 (2010/05/01) 戻り値に、true/false 指定します。 346 * 347 * @param fromFile コピー元ファイル名 348 * @param toFile コピー先ファイル名 349 * @param keepTimeStamp タイムスタンプ維持[true/false] 350 * 351 * @return バイナリコピーが正常に終了したかどうか[true:成功/false:失敗] 352 * @see #copy( File,File,boolean ) 353 */ 354 public static boolean copy( final String fromFile,final String toFile,final boolean keepTimeStamp ) { 355 return copy( new File( fromFile ), new File( toFile ), keepTimeStamp ); 356 } 357 358 /** 359 * ファイルのバイナリコピーを行います。 360 * 361 * copy( File,File,false ) を呼び出します。 362 * 363 * @og.rev 5.1.6.0 (2010/05/01) 戻り値に、true/false 指定します。 364 * 365 * @param fromFile コピー元ファイル 366 * @param toFile コピー先ファイル 367 * 368 * @return バイナリコピーが正常に終了したかどうか[true:成功/false:失敗] 369 * @see #copy( File,File,boolean ) 370 */ 371 public static boolean copy( final File fromFile,final File toFile ) { 372 return copy( fromFile, toFile, false ); 373 } 374 375 /** 376 * ファイルのバイナリコピーを行います。 377 * 378 * 第3引数の、keepTimeStamp=true で、コピー元のファイルのタイムスタンプを、 379 * コピー先にもセットします。 380 * toFile が、ディレクトリの場合は、fromFile のファイル名をそのままコピーします。 381 * fromFile がディレクトリの場合は、copyDirectry( File,Fileboolean )を call します。 382 * 383 * @og.rev 5.1.6.0 (2010/05/01) 新規追加 384 * @og.rev 5.6.5.2 (2013/06/21) ByteBufferを利用した方式から、transferTo を使用する方式に変更 385 * @og.rev 5.7.1.2 (2013/12/20) copy先(toFile)のフォルダが存在しなければ、作成します。 386 * @og.rev 6.3.6.1 (2015/08/28) copy元(fromFile)がフォルダがディレクトリの場合は、#copyDirectry( File,File,boolean ) を呼ぶ。 387 * @og.rev 6.3.6.1 (2015/08/28) Exception発生時に return ではなく、StringUtil.ogErrMsg に変更。 388 * @og.rev 6.3.8.5 (2015/10/16) StringUtil.ogErrMsgPrint 使用。 389 * @og.rev 6.4.2.0 (2016/01/29) StringUtil#ogErrMsgPrint(String,Throwable) を、ThrowUtilt#ogThrowMsg(String,Throwable) に変更。 390 * @og.rev 5.10.9.0 (2019/3/1) FileがFileOperationを生成している場合、指定の処理を行います。(クラウドストレージ対応) 391 * 392 * @param fromFile コピー元ファイル 393 * @param toFile コピー先ファイル 394 * @param keepTimeStamp タイムスタンプ維持[true/false] 395 * 396 * @return バイナリコピーが正常に終了したかどうか[true:成功/false:失敗] 397 * @see #copyDirectry( File,File,boolean ) 398 */ 399 public static boolean copy( final File fromFile,final File toFile,final boolean keepTimeStamp ) { 400 FileInputStream inFile = null; 401 FileOutputStream outFile = null; 402 FileChannel fin = null; 403 FileChannel fout = null; 404 InputStream is = null; // 5.10.9.0 (2019/3/1) ADD 405 406 File tempToFile = toFile ; 407 try { 408 // fromFileが、ディレクトリの場合は、エラー 409 if( fromFile.isDirectory() ) { 410 // 6.3.6.1 (2015/08/28) 411 return copyDirectry( fromFile,toFile,keepTimeStamp ); 412 } 413 // toFileが、ディレクトリの場合は、そのパスでファイル名をfromFileから取り出す。 414 if( toFile.isDirectory() ) { 415// tempToFile = new File( toFile,fromFile.getName() ); 416 if( toFile instanceof FileOperation ) { 417 tempToFile = FileOperationFactory.newStorageOperation( toFile, toFile.getAbsolutePath(), fromFile.getName() ); 418 }else { 419 tempToFile = new File( toFile,fromFile.getName() ); 420 } 421 } 422 423 // 5.7.1.2 (2013/12/20) copy先(toFile)のフォルダが存在しなければ、作成します。 424 final File parent = tempToFile.getParentFile(); 425 if( !parent.exists() && !parent.mkdirs() ) { 426 // ディレクトリを作成する 427 System.err.println( parent + " の ディレクトリ作成に失敗しました。" ); 428 return false; 429 } 430 431 // 5.10.9.0 (2019/3/1) MODIFY toFile,fromFileがFileOperationの場合は、FileOperation用のコピー処理を行います。 432 if(toFile instanceof FileOperation) { 433 if(fromFile instanceof FileOperation) { 434 // 両方がFileOperationの場合 435 is = ((FileOperation)fromFile).read(); 436 }else { 437 // toFileのみがFileOperationの場合 438 is = new FileInputStream(fromFile); 439 } 440 ((FileOperation) toFile).write(is); 441 }else if(fromFile instanceof FileOperation) { 442 // fromFileのみがFileOperationの場合 443 is = ((FileOperation)fromFile).read(); 444 Files.copy(is, toFile.toPath(), StandardCopyOption.REPLACE_EXISTING); 445 }else { 446 inFile = new FileInputStream( fromFile ); 447 outFile = new FileOutputStream( tempToFile ); 448 449 fin = inFile.getChannel(); 450 fout = outFile.getChannel(); 451 452 // 5.6.5.2 (2013/06/21) ByteBufferを利用した方式から、transferTo を使用する方式に変更 453 fin.transferTo(0, fin.size(), fout ); 454 } 455 } 456 catch( final IOException ex ) { 457 // 6.3.6.1 (2015/08/28) Exception発生時に return ではなく、StringUtil.ogErrMsg に変更。 458 final String errMsg = "バイナリコピーで、エラーが発生しました。" + CR 459 + "fromFile=[" + fromFile + "]" + CR 460 + "toFile =[" + toFile + "]" + CR ; 461 // 6.3.8.5 (2015/10/16) StringUtil.ogErrMsgPrint 使用。 462 System.out.println( ThrowUtil.ogThrowMsg( errMsg , ex ) ); // 6.4.2.0 (2016/01/29) 463 return false; 464 } 465 finally { 466 Closer.ioClose( inFile ) ; 467 Closer.ioClose( outFile ); 468 Closer.ioClose( fin ) ; 469 Closer.ioClose( fout ); 470 Closer.ioClose( is ); // 5.10.9.0 (2019/3/1) 471 } 472 473 if( keepTimeStamp ) { 474 return tempToFile.setLastModified( fromFile.lastModified() ); 475 } 476 477 return true; 478 } 479 480 /** 481 * ファイルのバイナリコピーを行います。 482 * 483 * このファイルコピーは、バイナリファイルの 改行コードを 484 * CR+LF に統一します。また、UTF-8 の BOM(0xef,0xbb,0xbf) があれば、 485 * 取り除きます。 486 * 487 * @og.rev 5.1.6.0 (2010/05/01) 新規追加 488 * @og.rev 6.3.6.1 (2015/08/28) Exception発生時に return ではなく、StringUtil.ogErrMsg に変更。 489 * @og.rev 6.3.8.5 (2015/10/16) StringUtil.ogErrMsgPrint 使用。 490 * @og.rev 6.4.2.0 (2016/01/29) StringUtil#ogErrMsgPrint(String,Throwable) を、ThrowUtilt#ogThrowMsg(String,Throwable) に変更。 491 * 492 * @param fromFile コピー元ファイル 493 * @param toFile コピー先ファイル 494 * 495 * @return バイナリコピーが正常に終了したかどうか[true:成功/false:失敗] 496 */ 497 public static boolean changeCrLfcopy( final File fromFile,final File toFile ) { 498 BufferedInputStream fromStream = null; 499 BufferedOutputStream toStream = null; 500 File tempToFile = toFile ; 501 try { 502 // ディレクトリの場合は、そのパスでファイル名をfromFileから取り出す。 503 if( toFile.isDirectory() ) { 504 tempToFile = new File( toFile,fromFile.getName() ); 505 } 506 fromStream = new BufferedInputStream( new FileInputStream( fromFile ) ); 507 toStream = new BufferedOutputStream( new FileOutputStream( tempToFile ) ); 508 509 final byte[] buf = new byte[BUFSIZE]; 510 int len ; 511 // 4.2.3.0 (2008/05/26) changeCrLf 属性対応 512 513 boolean bomCheck = true; // 最初の一回だけ、BOMチェックを行う。 514 byte bt = (byte)0x00; // バッファの最後と最初の比較時に使用 515 while( (len = fromStream.read(buf,0,BUFSIZE)) != -1 ) { 516 int st = 0; 517 if( bomCheck && len >= 3 && 518 buf[0] == (byte)0xef && 519 buf[1] == (byte)0xbb && 520 buf[2] == (byte)0xbf ) { 521 st = 3; 522 } 523 else { 524 // バッファの最後が CR で、先頭が LF の場合、LF をパスします。 525 if( bt == B_CR && buf[0] == B_LF ) { 526 st = 1 ; 527 } 528 } 529 bomCheck = false; 530 531 for( int i=st;i<len;i++ ) { 532 bt = buf[i] ; 533 if( bt == B_CR || bt == B_LF ) { 534 toStream.write( (int)B_CR ); // CR 535 toStream.write( (int)B_LF ); // LF 536 // CR+LF の場合 537 if( bt == B_CR && i+1 < len && buf[i+1] == B_LF ) { 538 i++; 539 bt = buf[i] ; 540 } 541 } 542 else { 543 toStream.write( (int)bt ); 544 } 545 } 546 } 547 // 最後が改行コードでなければ、改行コードを追加します。 548 // テキストコピーとの互換性のため 549 if( bt != B_CR && bt != B_LF ) { 550 toStream.write( (int)B_CR ); // CR 551 toStream.write( (int)B_LF ); // LF 552 } 553 } 554 catch( final IOException ex ) { 555 // 6.3.6.1 (2015/08/28) Exception発生時に return ではなく、StringUtil.ogErrMsg に変更。 556 final String errMsg = "バイナリコピー(CrLf)で、エラーが発生しました。" + CR 557 + "fromFile=[" + fromFile + "]" + CR 558 + "toFile =[" + toFile + "]" + CR ; 559 // 6.3.8.5 (2015/10/16) StringUtil.ogErrMsgPrint 使用。 560 System.out.println( ThrowUtil.ogThrowMsg( errMsg , ex ) ); // 6.4.2.0 (2016/01/29) 561 return false; 562 } 563 finally { 564 Closer.ioClose( fromStream ) ; 565 Closer.ioClose( toStream ) ; 566 } 567 568 return true; 569 } 570 571 /** 572 * ファイルのバイナリコピーを行います。 573 * 574 * コピー元のファイルは、InputStream で指定します。 575 * 元は、jsp/common 以下を圧縮、jar化したため、物理ファイルの取得が 576 * できなくなったため、ServletContext#getServletContext() で、ローカルリソースを 577 * 取得するのが目的です。汎用的に、入力は、InputStream にしました。 578 * URLConnection 等で、取得する場合は、BASIC認証も考慮する必要がありますので、 579 * ご注意ください。 580 * タイムスタンプのコピーは行いません。 581 * 582 * @og.rev 6.3.6.1 (2015/08/28) InputStreamで指定されたファイルのコピー 583 * @og.rev 6.3.8.5 (2015/10/16) StringUtil.ogErrMsgPrint 使用。 584 * @og.rev 6.4.2.0 (2016/01/29) StringUtil#ogErrMsgPrint(String,Throwable) を、ThrowUtilt#ogThrowMsg(String,Throwable) に変更。 585 * 586 * @param inStrm コピー元のInputStream(この中でcloseします) 587 * @param toFile コピー先ファイル 588 * 589 * @return バイナリコピーが正常に終了したかどうか[true:成功/false:失敗] 590 * @see #copy( File,File ) 591 */ 592 public static boolean copy( final InputStream inStrm,final File toFile ) { 593 FileOutputStream foStrm = null; 594 try { 595 // copy先(toFile)のフォルダが存在しなければ、作成します。 596 final File parent = toFile.getParentFile(); 597 if( !parent.exists() && !parent.mkdirs() ) { 598 // ディレクトリを作成する 599 System.err.println( parent + " の ディレクトリ作成に失敗しました。" ); 600 return false; 601 } 602 603 foStrm = new FileOutputStream( toFile, false ); 604 return copy( inStrm , foStrm ); 605 } 606 catch( final IOException ex ) { 607 // 6.3.6.1 (2015/08/28) Exception発生時に return ではなく、StringUtil.ogErrMsg に変更。 608 final String errMsg = "入力ストリームのコピーでエラーが発生しました。" + CR 609 + "toFile =[" + toFile + "]" + CR ; 610 // 6.3.8.5 (2015/10/16) StringUtil.ogErrMsgPrint 使用。 611 System.out.println( ThrowUtil.ogThrowMsg( errMsg , ex ) ); // 6.4.2.0 (2016/01/29) 612 } 613 finally { 614 Closer.ioClose( inStrm ); 615 Closer.ioClose( foStrm ); 616 } 617 618 return false ; 619 } 620 621 /** 622 * 入出力ストリーム間でデータの転送を行います。 623 * 624 * ここでは、すでに作成されたストリームに基づき、データの入出力を行います。 625 * よって、先にフォルダ作成や、存在チェック、ファイルの削除などの必要な処理は 626 * 済まして置いてください。 627 * また、このメソッド内で、ストリームのクロース処理は行っていません。 628 * 629 * @og.rev 5.1.6.0 (2010/05/01) 新規追加 630 * @og.rev 6.3.6.1 (2015/08/28) エラー時のメッセージ情報を増やします。 631 * @og.rev 6.3.8.5 (2015/10/16) StringUtil#ogErrMsgPrint 使用。 632 * @og.rev 6.4.2.0 (2016/01/29) StringUtil#ogErrMsgPrint(String,Throwable) を、ThrowUtilt#ogThrowMsg(String,Throwable) に変更。 633 * 634 * @param input 入力ストリーム 635 * @param output 出力ストリーム 636 * 637 * @return データ転送が正常に終了したかどうか[true:成功/false:失敗] 638 */ 639 public static boolean copy( final InputStream input,final OutputStream output ) { 640 if( input == null ) { 641 final String errMsg = "入力ストリームが 作成されていません。" ; 642 // 6.3.8.5 (2015/10/16) StringUtil.ogErrMsgPrint 使用。 643 System.out.println( ThrowUtil.ogThrowMsg( errMsg ) ); // 6.4.2.0 (2016/01/29) 644 return false; 645 } 646 647 if( output == null ) { 648 final String errMsg = "出力ストリームが 作成されていません。" ; 649 // 6.3.8.5 (2015/10/16) StringUtil.ogErrMsgPrint 使用。 650 System.out.println( ThrowUtil.ogThrowMsg( errMsg ) ); // 6.4.2.0 (2016/01/29) 651 return false; 652 } 653 654 try { 655 final byte[] buf = new byte[BUFSIZE]; 656 int len; 657 while((len = input.read(buf)) != -1) { 658 output.write(buf, 0, len); 659 } 660 } 661 catch( final IOException ex ) { 662 final String errMsg = "ストリームデータの入出力処理に失敗しました。"; 663 // 6.3.8.5 (2015/10/16) StringUtil.ogErrMsgPrint 使用。 664 System.out.println( ThrowUtil.ogThrowMsg( errMsg,ex ) ); // 6.4.2.0 (2016/01/29) 665 return false; 666 } 667 // finally { 668 // Closer.ioClose( input ); 669 // Closer.ioClose( output ); 670 // } 671 return true ; 672 } 673 674 /** 675 * 再帰処理でディレクトリのコピーを行います。 676 * 677 * 指定されたコピー元ディレクトリがディレクトリでなかったり存在しないときは falseを返します。 678 * 679 * @og.rev 4.3.0.0 (2008/07/24) 追加 680 * @og.rev 5.1.6.0 (2010/05/01) 戻り値に、true/false 指定します。 681 * 682 * @param fromDir コピー元ディレクトリ名 683 * @param toDir コピー先ディレクトリ名 684 * 685 * @return ディレクトリのコピーが正常に終了したかどうか[true:成功/false:失敗] 686 */ 687 public static boolean copyDirectry( String fromDir, final String toDir ) { 688 return copyDirectry( new File( fromDir ), new File( toDir ),false ); 689 } 690 691 /** 692 * 再帰処理でディレクトリをコピーします。 693 * 694 * 指定されたコピー元ディレクトリがディレクトリでなかったり存在しないときは falseを返します。 695 * 696 * @og.rev 4.3.0.0 (2008/07/24) 追加 697 * @og.rev 5.1.6.0 (2010/05/01) 内部処理を若干変更します。 698 * 699 * @param fromDir コピー元ディレクトリ 700 * @param toDir コピー先ディレクトリ 701 * 702 * @return ディレクトリのコピーが正常に終了したかどうか[true:成功/false:失敗] 703 */ 704 public static boolean copyDirectry( File fromDir, final File toDir ) { 705 return copyDirectry( fromDir, toDir, false ); 706 } 707 708 /** 709 * 再帰処理でディレクトリをコピーします。 710 * 711 * 指定されたコピー元ディレクトリがディレクトリでなかったり存在しないときは falseを返します。 712 * 713 * @og.rev 4.3.0.0 (2008/07/24) 追加 714 * @og.rev 5.1.6.0 (2010/05/01) 内部処理を若干変更します。 715 * @og.rev 5.3.7.0 (2011/07/01) フォルダにアクセスできない場合は、エラーを返します。 716 * 717 * @param fromDir コピー元ディレクトリ 718 * @param toDir コピー先ディレクトリ 719 * @param keepTimeStamp タイムスタンプ維持[true/false] 720 * 721 * @return ディレクトリのコピーが正常に終了したかどうか[true:成功/false:失敗] 722 */ 723 public static boolean copyDirectry( File fromDir, final File toDir, final boolean keepTimeStamp ) { 724 // コピー元がディレクトリでない場合はfalseを返す 725 // 4.3.4.4 (2009/01/01) 726 if( !fromDir.exists() || !fromDir.isDirectory() ) { 727 System.err.println( fromDir + " が ディレクトリでないか、存在しません。" ); 728 return false; 729 } 730 731 // 4.3.4.4 (2009/01/01) ディレクトリを作成する 732 // 6.0.0.1 (2014/04/25) These nested if statements could be combined 733 if( !toDir.exists() && !toDir.mkdirs() ) { 734 System.err.println( toDir + " の ディレクトリ作成に失敗しました。" ); 735 return false; 736 } 737 738 // ディレクトリ内のファイルをすべて取得する 739 final File[] files = fromDir.listFiles(); 740 741 // 5.3.7.0 (2011/07/01) フォルダにアクセスできない場合は、エラー 742 if( files == null ) { 743 System.err.println( fromDir + " はアクセスできません。" ); 744 return false; 745 } 746 747 // ディレクトリ内のファイルに対しコピー処理を行う 748 boolean flag = true; 749 for( int i=0; files.length>i; i++ ){ 750 if( files[i].isDirectory() ){ // ディレクトリだった場合は再帰呼び出しを行う 751 flag = copyDirectry( files[i], new File( toDir, files[i].getName()),keepTimeStamp ); 752 } 753 else{ // ファイルだった場合はファイルコピー処理を行う 754 flag = copy( files[i], new File( toDir, files[i].getName()),keepTimeStamp ); 755 } 756 if( !flag ) { return false; } 757 } 758 return true; 759 } 760 761 /** 762 * 指定されたファイル及びディレクトを削除します。 763 * ディレクトリの場合はサブフォルダ及びファイルも削除します。 764 * 1つでもファイルの削除に失敗した場合、その時点で処理を中断しfalseを返します。 765 * 766 * @og.rev 5.3.7.0 (2011/07/01) フォルダにアクセスできない場合は、エラーを返します。 767 * 768 * @param file 削除ファイル/ディレクトリ 769 * 770 * @return ファイル/ディレクトリの削除に終了したかどうか[true:成功/false:失敗] 771 */ 772 public static boolean deleteFiles( final File file ) { 773 if( file.exists() ) { 774 if( file.isDirectory() ) { 775 final File[] list = file.listFiles(); 776 777 // 5.3.7.0 (2011/07/01) フォルダにアクセスできない場合は、エラー 778 if( list == null ) { 779 System.err.println( file + " はアクセスできません。" ); 780 return false; 781 } 782 783 for( int i=0; i<list.length; i++ ) { 784 deleteFiles( list[i] ); 785 } 786 } 787 if( !file.delete() ) { return false; } 788 } 789 return true; 790 } 791 792 /** 793 * 指定されたディレクトリを基点としたファイル名(パスを含む)の一覧を返します。 794 * 互換性のため、コピー中ファイルも含みます。 795 * 796 * @og.rev 5.4.3.2 (2012/01/06) コピー中対応のため引数4つを作成する 797 * 798 * @param dir 基点となるディレクトリ 799 * @param sort ファイル名でソートするか 800 * @param list ファイル名一覧を格納するList 801 */ 802 public static void getFileList( final File dir, final boolean sort, final List<String> list ) { 803// getFileList( dir, sort, list, true ); 804 getFileList( dir, null, sort, list, true ); // 7.0.1.4 (2018/11/26) FileFilter を利用 805 } 806 807 /** 808 * 指定されたディレクトリを基点としたファイル名(パスを含む)の一覧を返します。 809 * 810 * @og.rev 4.3.6.6 (2009/05/15) 新規作成 811 * @og.rev 5.4.3.2 (2012/01/06) 引数isCopy追加 812 * @og.rev 6.3.9.0 (2015/11/06) null になっている可能性があるメソッドの戻り値のnullチェックを追加。 813 * 814 * @param dir 基点となるディレクトリ 815 * @param sort ファイル名でソートするか 816 * @param list ファイル名一覧を格納するList 817 * @param isCopy コピー中ファイルを除外するか [true:含む/false:除外] 818 */ 819 public static void getFileList( final File dir, final boolean sort, final List<String> list, final boolean isCopy ) { 820 getFileList( dir, null, sort, list, true ); // 7.0.1.4 (2018/11/26) FileFilter を利用 821 822// if( list == null ) { return; } 823// if( dir.isFile() ) { 824// // コピー中判定はrenameで行う 825// // 6.1.0.0 (2014/12/26) refactoring : Avoid if(x != y) ..; else ..; 826// if( isCopy || dir.renameTo( dir ) ) { 827// list.add( dir.getAbsolutePath() ); 828// } 829// else{ 830// return; 831// } 832// } 833// else if( dir.isDirectory() ) { 834// final File[] files = dir.listFiles(); 835// // 6.3.9.0 (2015/11/06) null になっている可能性があるメソッドの戻り値のnullチェックを追加。 836// if( files != null ) { 837// for( int i=0; i<files.length; i++ ) { 838// getFileList( files[i], sort, list, isCopy ); 839// } 840// } 841// } 842// if( sort ) { 843// Collections.sort( list ); 844// } 845 } 846 847 /** 848 * 指定されたディレクトリを基点としたファイル名(パスを含む)の一覧を返します。 849 * 850 * @og.rev 4.3.6.6 (2009/05/15) 新規作成 851 * @og.rev 5.4.3.2 (2012/01/06) 引数isCopy追加 852 * @og.rev 6.3.9.0 (2015/11/06) null になっている可能性があるメソッドの戻り値のnullチェックを追加。 853 * @og.rev 7.0.1.4 (2018/11/26) FileFilter を利用して、フォルダの絞り込みを行う。 854 * 855 * @param dir 基点となるディレクトリ 856 * @param filter ディレクトリやファイルを絞り込むフィルター(nullの場合は、すべてOK) 857 * @param sort ファイル名でソートするか 858 * @param list ファイル名一覧を格納するList 859 * @param isCopy コピー中ファイルを除外するか [true:含む/false:除外] 860 */ 861 public static void getFileList( final File dir, final FileFilter filter, final boolean sort, final List<String> list, final boolean isCopy ) { 862 if( list == null ) { return; } 863 if( dir.isFile() ) { 864 // コピー中判定はrenameで行う 865 // 6.1.0.0 (2014/12/26) refactoring : Avoid if(x != y) ..; else ..; 866 if( isCopy || dir.renameTo( dir ) ) { 867 list.add( dir.getAbsolutePath() ); 868 } 869 else{ 870 return; 871 } 872 } 873 else if( dir.isDirectory() ) { 874// final File[] files = dir.listFiles(); 875 final File[] files = dir.listFiles( filter ); 876 // 6.3.9.0 (2015/11/06) null になっている可能性があるメソッドの戻り値のnullチェックを追加。 877 if( files != null ) { 878 for( int i=0; i<files.length; i++ ) { 879 getFileList( files[i], sort, list, isCopy ); 880 } 881 } 882 } 883 if( sort ) { 884 Collections.sort( list ); 885 } 886 } 887 888 /** 889 * ファイルをリネームを行います。 890 * 引数のuseBackup属性を true にすると、toFile が存在した場合、toFile の直下に "_backup" フォルダを 891 * 作成して、toFile + "_" + (現在時刻のLONG値) + "." + (toFileの拡張子) に名前変更します。 892 * useBackup属性を rename にすると、toFile が存在した場合、toFile に、"_001" からなる 893 * 連番を付与し、重複しなくなるまで、名前を変更します。 894 * useBackup属性を false(またはnull) にすると、toFile が存在した場合、toFile を削除します。 895 * 896 * 戻り値は、変更後のファイルオブジェクトです。 897 * 898 * @og.rev 5.7.1.2 (2013/12/20) 新規追加 899 * @og.rev 6.0.2.4 (2014/10/17) useBackup の機能追加 900 * @og.rev 6.2.0.0 (2015/02/27) FileInfoクラスを使用。 (#getFileSplit(File)の結果配列は廃止) 901 * @og.rev 5.9.10.0 (2019/03/01) FileOperation対応 902 * 903 * @param fromFile 名前変更する元のファイル 904 * @param toFile 名前変更後のファイル 905 * @param useBackup 置き換えファイルの処理方法(true:backupフォルダ/false:しない/rename:重複しない連番) 906 * @return 名前変更後のファイル 907 * @throws RuntimeException 名称変更処理ができなかった場合。 908 */ 909 public static File renameTo( final File fromFile , final File toFile , final String useBackup ) { 910 if( fromFile == null || toFile == null ) { 911 final String errMsg = "入力ファイルが null です。from=[" + fromFile + "] , to=[" + toFile + "]" ; 912 throw new OgRuntimeException( errMsg ); 913 } 914 915 final File parent = toFile.getParentFile(); // 6.0.2.4 (2014/10/17) toFile のフォルダがなければ作成 916 if( !parent.exists() && !parent.mkdirs() ) { 917 final String errMsg = "toファイルのフォルダが作成できません。from=[" + fromFile + "] , to=[" + toFile + "]" ; 918 throw new OgRuntimeException( errMsg ); 919 } 920 921 // 変更先のファイルが存在した場合の処理。 922 File newFile = toFile; // useBackup = "rename" の時のみ書き換えたいので。 923 if( toFile.exists() ) { 924 final FileInfo info = new FileInfo( toFile ); // 6.2.0.0 (2015/02/27) 925 // バックアップ作成する場合 926 // 6.0.2.4 (2014/10/17) useBackup は、文字列で、true/false,(null)/rename がある。 927 if( "true".equalsIgnoreCase( useBackup ) ) { 928// final File backup = new File( parent , "_backup" ); // その直下に、"_backup" フォルダを作成 929 final File backup = FileOperationFactory.newStorageOperation(toFile, parent.getPath(), "_backup"); // 5.10.9.0 (2019/03/01) 930 if( !backup.exists() && !backup.mkdirs() ) { 931 final String errMsg = "バックアップ処理でbackupフォルダの作成に失敗しました。[" + backup + "]"; 932 throw new OgRuntimeException( errMsg ); 933 } 934 // バックアップファイル名は、元のファイル名(拡張子含む) + "_" + 現在時刻のlong値 + "." + 元のファイルの拡張子 935 final String toName = toFile.getName(); 936// final File toFile2 = new File( parent,toName ); // オリジナルの toFile をrename するとまずいので、同名のFileオブジェクトを作成 937 final File toFile2 = FileOperationFactory.newStorageOperation(toFile, parent.getPath(), toName); // 5.10.9.0 (2019/03/01) 938 939 final String bkupName = info.NAME + "_" + System.currentTimeMillis() + "." + info.SUFIX ; // 6.2.0.0 (2015/02/27) 940// final File bkupFile = new File( backup,bkupName ); 941 final File bkupFile = FileOperationFactory.newStorageOperation(backup, backup.getParent(), bkupName); // 5.10.9.0 (2019/03/01) 942 943 if( !toFile2.renameTo( bkupFile ) ) { 944 final String errMsg = "バックアップ処理でバックアップファイルをリネームできませんでした。" +CR 945 + " [" + toFile + "] ⇒ [" + bkupFile + "]" ; 946 throw new OgRuntimeException( errMsg ); 947 } 948 } 949 // 他と違い、toFile を変更する必要がある。 950 else if( "rename".equalsIgnoreCase( useBackup ) ) { 951 for( int i=1000; i<2000; i++ ) { // 000 の3桁を取得したいため。 952 final String no = String.valueOf( i ).substring(1); 953 // 6.2.0.0 (2015/02/27) 配列ではなく、FileInfoクラスを使用 954// final File toFile2 = new File( info.DIR , info.NAME + "_" + no + "." + info.SUFIX ); 955 final File toFile2 = FileOperationFactory.newStorageOperation(toFile, info.DIR, info.NAME + "_" + no + "." + info.SUFIX); // 5.10.9.0 (2019/03/01) 956 if( !toFile2.exists() ) { 957 newFile = toFile2; 958 break; 959 } 960 } 961 } 962 // バックアップ作成しない場合は、削除します。 963 else if( !toFile.delete() ) { 964 final String errMsg = "既存のファイル[" + toFile + "]が削除できませんでした。"; 965 throw new OgRuntimeException( errMsg ); 966 } 967 } 968 969 if( !fromFile.renameTo( newFile ) ) { 970 final String errMsg = "所定のファイルをリネームできませんでした。" + CR 971 + " [" + fromFile + "] ⇒ [" + newFile + "]" ; 972 throw new OgRuntimeException( errMsg ); 973 } 974 return newFile; 975 } 976 977 /** 978 * ファイルを読み取って、文字列を作成します。 979 * 980 * データの読取が完全に出来なかったときには、途中までのデータを返します。 981 * 指定のエンコードが存在しない場合や、ファイルが存在しない場合は、 982 * OgRuntimeException を throw します。 983 * encode が null の場合は、UTF-8 で読み込みます。 984 * 985 * @og.rev 6.4.2.0 (2016/01/29) fukurou.util.StringUtil → fukurou.system.HybsConst に変更 986 * @og.rev 6.4.5.1 (2016/04/28) encode は初期化しているため、null はセットされません。 987 * @og.rev 6.4.5.2 (2016/05/06) fukurou.util.FileString から、fukurou.util.FileUtil に移動。 988 * 989 * @param filename ファイル名 990 * @param encode エンコード名 991 * @return ファイルを読み取った文字列 992 * @throws RuntimeException 指定のエンコードが存在しなかったとき。 993 */ 994 public static String getValue( final String filename , final String encode ) { 995 if( filename == null ) { 996 final String errMsg = "ファイル名が指定されていません。" ; 997 throw new OgRuntimeException( errMsg ); 998 } 999 1000 final String enc = encode == null ? HybsConst.UTF_8 : encode ; 1001 1002 try { 1003 return new String( Files.readAllBytes( new File( filename ).toPath() ),enc ); 1004 } 1005 catch( final IOException ex ) { 1006 final String errMsg = "ファイル名がオープン出来ませんでした。[" + filename + "]" ; 1007 throw new OgRuntimeException( errMsg,ex ); 1008 } 1009 } 1010 1011 /** 1012 * 改行コードで分割して、Listオブジェクトを返します。 1013 * 1014 * encode が null の場合は、UTF-8 で読み込みます。 1015 * 1016 * @og.rev 6.4.5.2 (2016/05/06) fukurou.util.FileString から、fukurou.util.FileUtil に移動。 1017 * 1018 * @param filename ファイル名 1019 * @param encode エンコード名 1020 * @return ファイルを読み取った文字列を分割したList 1021 */ 1022 public static List<String> getLineList( final String filename , final String encode ) { 1023 try { 1024 final String enc = encode == null ? HybsConst.UTF_8 : encode ; 1025 1026 return Files.readAllLines( new File( filename ).toPath() , Charset.forName( enc ) ); 1027 } 1028 catch( final IOException ex ) { 1029 final String errMsg = "ファイル名がオープン出来ませんでした。[" + filename + "]" ; 1030 throw new OgRuntimeException( errMsg,ex ); 1031 } 1032 } 1033 1034 /** 1035 * Fileオブジェクトのサイズを返します。 1036 * 1037 * オブジェクトが通常のファイルの場合は、そのファイルサイズを返します。 1038 * フォルダの場合は、再帰的に、ファイルサイズを加算した結果を返します。 1039 * 1040 * @og.rev 6.7.4.1 (2017/02/17) Fileオブジェクトのサイズを返します。 1041 * 1042 * @param file Fileオブジェクト 1043 * @return ファイルまたはフォルダののサイズ 1044 */ 1045 public static long length( final File file ) { 1046 if( file.isDirectory() ) { 1047 final File[] children = file.listFiles(); 1048 1049 long sum = 0; 1050 if( children != null ) { 1051 for( final File child : children ) { 1052 sum += length( child ); 1053 } 1054 } 1055 return sum; 1056 } 1057 return file.length(); 1058 } 1059 1060 /** 1061 * PrintWriter を継承した、System.out/System.err 用のクラスを定義します。 1062 * 1063 * 通常の、new PrintWriter( OutputStream ) で、求めるのと、ほとんど同様の 1064 * 処理を行います。 1065 * ただ、close() メソッドが呼ばれても、何もしません。 1066 * 1067 */ 1068 private static final class NonClosePrintWriter extends PrintWriter { 1069 /** 1070 * コンストラクター 1071 * 1072 * new PrintWriter( OutputStream ) を行います。 1073 * 1074 * @param out OutputStreamオブジェクト 1075 */ 1076 public NonClosePrintWriter( final OutputStream out ) { 1077 super( out ); 1078 } 1079 1080 /** 1081 * close() メソッドをオーバーライドします。 1082 * 1083 * 何もしません。 1084 */ 1085 @Override 1086 public void close() { 1087 // ここでは処理を行いません。 1088 } 1089 } 1090 1091 /** 1092 * PrintWriter を継承した、JspWriterなどの Writer 用のクラスを定義します。 1093 * 1094 * 例えば、JspWriterなどの JSP/Servlet等のフレームワークで使用される 1095 * Writer では、flush や close 処理は、フレームワーク内で行われます。 1096 * その場合、通常のファイルと同じ用に、flush や close をアプリケーション側で 1097 * 行うと、内部処理的に不整合が発生したり、最悪の場合エラーになります。 1098 * このクラスは、単に、通常の、new PrintWriter( Writer ) で、求めるのと、 1099 * ほとんど同様の処理を行います。 1100 * ただ、close() と flush() メソッドが呼ばれても、何もしません。 1101 * 1102 */ 1103 private static final class NonFlushPrintWriter extends PrintWriter { 1104 /** 1105 * コンストラクター 1106 * 1107 * new PrintWriter( Writer ) を行います。 1108 * 1109 * @param writer Writerオブジェクト 1110 */ 1111 public NonFlushPrintWriter( final Writer writer ) { 1112 super( writer ); 1113 } 1114 1115 /** 1116 * close() メソッドをオーバーライドします。 1117 * 1118 * 何もしません。 1119 */ 1120 @Override 1121 public void close() { 1122 // ここでは処理を行いません。 1123 } 1124 1125 /** 1126 * flush() メソッドをオーバーライドします。 1127 * 1128 * 何もしません。 1129 */ 1130 @Override 1131 public void flush() { 1132 // ここでは処理を行いません。 1133 } 1134 } 1135 1136 /** 1137 * ファイルのエンコードを変換するコピーを行います。 1138 * 1139 * copy( File,File,false ) を呼び出します。 1140 * 1141 * @og.rev 5.1.6.0 (2010/05/01) 戻り値に、true/false 指定します。 1142 * 1143 * @param file1 コピー元ファイル名 1144 * @param file2 コピー先ファイル名 1145 * @param encode1 コピー元ファイルのエンコード 1146 * @param encode2 コピー先ファイルのエンコード 1147 * 1148 * @see #copy( File,File,boolean ) 1149 */ 1150 public static void copy( final File file1,final File file2,final String encode1,final String encode2 ) { 1151 // final File tempFile = new File( file2.getName() + "_backup" ); 1152 1153 // FileUtil.copy( file2,tempFile ); 1154 1155 final BufferedReader reader = FileUtil.getBufferedReader( file1 ,encode1 ); 1156 final PrintWriter writer = FileUtil.getPrintWriter( file2 ,encode2 ); 1157 1158 try { 1159 String line1; 1160 while((line1 = reader.readLine()) != null) { 1161 writer.println( line1 ); 1162 } 1163 } 1164 catch( final Throwable th ) { 1165 th.printStackTrace(); 1166 } 1167 finally { 1168 Closer.ioClose( reader ) ; 1169 Closer.ioClose( writer ) ; 1170 } 1171 1172 // 6.9.8.0 (2018/05/28) FindBugs:例外的戻り値を無視しているメソッド 1173// file2.setLastModified( file1.lastModified() ); 1174 if( !file2.setLastModified( file1.lastModified() ) ) { 1175 final String errMsg = "FileUtil.copy において、タイムスタンプの更新が出来ませんでした。" + CR 1176 + " file2= [" + file2 + "]" + CR ; 1177 System.err.println( errMsg ); 1178 } 1179 } 1180 1181 /** 1182 * ファイルをコピーします。 1183 * 1184 * 引数に <file1> <file2> [<encode1> <encode2>] を指定します。 1185 * file1 を読み込み、file2 にコピーします。コピー前に、file2 は、file2_backup にコピーします。 1186 * file1 が、ディレクトリの場合は、ディレクトリごとコピーします。 1187 * encode1、encode2 を指定すると、エンコード変換しながらコピーになります。 1188 * この場合は、ファイル同士のコピーのみになります。 1189 * 1190 * @og.rev 4.0.0.0 (2007/11/28) メソッドの戻り値をチェックします。 1191 * @og.rev 5.1.6.0 (2010/05/01) 引数の並び順、処理を変更します。 1192 * 1193 * @param args 引数配列 file1 file2 [encode1 encode2] 1194 * @throws Throwable なんらかのエラーが発生した場合。 1195 */ 1196 public static void main( final String[] args ) throws Throwable { 1197 if( args.length != 2 && args.length != 4 ) { 1198 LogWriter.log("Usage: java org.opengion.fukurou.util.FileUtil <file1> <file2> [<encode1> <encode2>]" ); 1199 return ; 1200 } 1201 1202 final File file1 = new File( args[0] ); 1203 final File file2 = new File( args[1] ); 1204 1205 if( args.length < 3 ) { 1206 if( file1.isDirectory() ) { 1207 FileUtil.copyDirectry( file1, file2, true ); 1208 } 1209 else { 1210 final File tempFile = new File( args[1] + "_backup" ); 1211 FileUtil.copy( file2,tempFile ); 1212 FileUtil.copy( file1,file2, true ); 1213 } 1214 } 1215 else { 1216 final String encode1 = args[2]; 1217 final String encode2 = args[3]; 1218 1219 if( file1.isDirectory() ) { 1220 final File[] children = file1.listFiles(); 1221 1222 if( children != null ) { 1223 for( final File child : children ) { 1224 copy( child , new File( file2 , child.getName() ),encode1,encode2 ); 1225 } 1226 } 1227 } 1228 else { 1229 copy( file1,file2,encode1,encode2 ); 1230 } 1231 } 1232 } 1233}