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 * @og.rev 8.0.0.1 (2021/10/08) クラウド修正 392 * @og.rev 8.4.1.2 (2023/03/03) toFile ではなく、tempToFile を使う必要がある。 393 * 394 * @param fromFile コピー元ファイル 395 * @param toFile コピー先ファイル 396 * @param keepTimeStamp タイムスタンプ維持[true/false] 397 * 398 * @return バイナリコピーが正常に終了したかどうか[true:成功/false:失敗] 399 * @see #copyDirectry( File,File,boolean ) 400 */ 401 public static boolean copy( final File fromFile,final File toFile,final boolean keepTimeStamp ) { 402 FileInputStream inFile = null; 403 FileOutputStream outFile = null; 404 FileChannel fin = null; 405 FileChannel fout = null; 406 InputStream is = null; // 5.10.9.0 (2019/3/1) ADD 407 408 File tempToFile = toFile ; 409 try { 410 // fromFileが、ディレクトリの場合は、copyDirectryで処理する。 411 if( fromFile.isDirectory() ) { 412 // 6.3.6.1 (2015/08/28) 413 return copyDirectry( fromFile,toFile,keepTimeStamp ); 414 } 415 // toFileが、ディレクトリの場合は、そのパスでファイル名をfromFileから取り出す。 416 if( toFile.isDirectory() ) { 417// tempToFile = new File( toFile,fromFile.getName() ); 418 // 5.10.9.0 (2019/3/1) MODIFY FileOperationの場合は、FileOperationFactoryを利用します。 419 if( toFile instanceof FileOperation ) { 420 // 8.0.0.1 (2021/10/08) クラウド修正 421// tempToFile = FileOperationFactory.newStorageOperation( toFile, toFile.getAbsolutePath(), fromFile.getName() ); 422 tempToFile = FileOperationFactory.resolveFile( toFile, toFile.getAbsolutePath(), fromFile.getName() ); 423 }else { 424 tempToFile = new File( toFile,fromFile.getName() ); 425 } 426 } 427 428 // 5.7.1.2 (2013/12/20) copy先(toFile)のフォルダが存在しなければ、作成します。 429 final File parent = tempToFile.getParentFile(); 430 if( !parent.exists() && !parent.mkdirs() ) { 431 // ディレクトリを作成する 432 System.err.println( parent + " の ディレクトリ作成に失敗しました。" ); 433 return false; 434 } 435 436 // 5.10.9.0 (2019/3/1) MODIFY toFile,fromFileがFileOperationの場合は、FileOperation用のコピー処理を行います。 437 if(toFile instanceof FileOperation) { 438 if(fromFile instanceof FileOperation) { 439 // 両方がFileOperationの場合 440 is = ((FileOperation)fromFile).read(); 441 }else { 442 // toFileのみがFileOperationの場合 443 is = new FileInputStream(fromFile); 444 } 445// ((FileOperation) toFile).write(is); 446 ((FileOperation) tempToFile).write(is); // 8.4.1.2 (2023/03/03) toFile ではなく、tempToFile を使う必要がある。 447 }else if(fromFile instanceof FileOperation) { 448 // fromFileのみがFileOperationの場合 449 is = ((FileOperation)fromFile).read(); 450// Files.copy(is, toFile.toPath(), StandardCopyOption.REPLACE_EXISTING); 451 Files.copy(is, tempToFile.toPath(), StandardCopyOption.REPLACE_EXISTING); // 8.4.1.2 (2023/03/03) toFile ではなく、tempToFile を使う必要がある。 452 }else { 453 inFile = new FileInputStream( fromFile ); 454 outFile = new FileOutputStream( tempToFile ); 455 456 fin = inFile.getChannel(); 457 fout = outFile.getChannel(); 458 459 // 5.6.5.2 (2013/06/21) ByteBufferを利用した方式から、transferTo を使用する方式に変更 460 fin.transferTo(0, fin.size(), fout ); 461 } 462 } 463 catch( final IOException ex ) { 464 // 6.3.6.1 (2015/08/28) Exception発生時に return ではなく、StringUtil.ogErrMsg に変更。 465 final String errMsg = "バイナリコピーで、エラーが発生しました。" + CR 466 + "fromFile=[" + fromFile + "]" + CR 467 + "toFile =[" + toFile + "]" + CR ; 468 // 6.3.8.5 (2015/10/16) StringUtil.ogErrMsgPrint 使用。 469 System.out.println( ThrowUtil.ogThrowMsg( errMsg , ex ) ); // 6.4.2.0 (2016/01/29) 470 return false; 471 } 472 finally { 473 Closer.ioClose( inFile ) ; 474 Closer.ioClose( outFile ); 475 Closer.ioClose( fin ) ; 476 Closer.ioClose( fout ); 477 Closer.ioClose( is ); // 5.10.9.0 (2019/3/1) 478 } 479 480 if( keepTimeStamp ) { 481 return tempToFile.setLastModified( fromFile.lastModified() ); 482 } 483 484 return true; 485 } 486 487 /** 488 * ファイルのバイナリコピーを行います。 489 * 490 * このファイルコピーは、バイナリファイルの 改行コードを 491 * CR+LF に統一します。また、UTF-8 の BOM(0xef,0xbb,0xbf) があれば、 492 * 取り除きます。 493 * 494 * @og.rev 5.1.6.0 (2010/05/01) 新規追加 495 * @og.rev 6.3.6.1 (2015/08/28) Exception発生時に return ではなく、StringUtil.ogErrMsg に変更。 496 * @og.rev 6.3.8.5 (2015/10/16) StringUtil.ogErrMsgPrint 使用。 497 * @og.rev 6.4.2.0 (2016/01/29) StringUtil#ogErrMsgPrint(String,Throwable) を、ThrowUtilt#ogThrowMsg(String,Throwable) に変更。 498 * 499 * @param fromFile コピー元ファイル 500 * @param toFile コピー先ファイル 501 * 502 * @return バイナリコピーが正常に終了したかどうか[true:成功/false:失敗] 503 */ 504 public static boolean changeCrLfcopy( final File fromFile,final File toFile ) { 505 BufferedInputStream fromStream = null; 506 BufferedOutputStream toStream = null; 507 File tempToFile = toFile ; 508 try { 509 // ディレクトリの場合は、そのパスでファイル名をfromFileから取り出す。 510 if( toFile.isDirectory() ) { 511 tempToFile = new File( toFile,fromFile.getName() ); 512 } 513 fromStream = new BufferedInputStream( new FileInputStream( fromFile ) ); 514 toStream = new BufferedOutputStream( new FileOutputStream( tempToFile ) ); 515 516 final byte[] buf = new byte[BUFSIZE]; 517 int len ; 518 // 4.2.3.0 (2008/05/26) changeCrLf 属性対応 519 520 boolean bomCheck = true; // 最初の一回だけ、BOMチェックを行う。 521 byte bt = (byte)0x00; // バッファの最後と最初の比較時に使用 522 while( (len = fromStream.read(buf,0,BUFSIZE)) != -1 ) { 523 int st = 0; 524 if( bomCheck && len >= 3 && 525 buf[0] == (byte)0xef && 526 buf[1] == (byte)0xbb && 527 buf[2] == (byte)0xbf ) { 528 st = 3; 529 } 530 else { 531 // バッファの最後が CR で、先頭が LF の場合、LF をパスします。 532 if( bt == B_CR && buf[0] == B_LF ) { 533 st = 1 ; 534 } 535 } 536 bomCheck = false; 537 538 for( int i=st;i<len;i++ ) { 539 bt = buf[i] ; 540 if( bt == B_CR || bt == B_LF ) { 541 toStream.write( (int)B_CR ); // CR 542 toStream.write( (int)B_LF ); // LF 543 // CR+LF の場合 544 if( bt == B_CR && i+1 < len && buf[i+1] == B_LF ) { 545 i++; 546 bt = buf[i] ; 547 } 548 } 549 else { 550 toStream.write( (int)bt ); 551 } 552 } 553 } 554 // 最後が改行コードでなければ、改行コードを追加します。 555 // テキストコピーとの互換性のため 556 if( bt != B_CR && bt != B_LF ) { 557 toStream.write( (int)B_CR ); // CR 558 toStream.write( (int)B_LF ); // LF 559 } 560 } 561 catch( final IOException ex ) { 562 // 6.3.6.1 (2015/08/28) Exception発生時に return ではなく、StringUtil.ogErrMsg に変更。 563 final String errMsg = "バイナリコピー(CrLf)で、エラーが発生しました。" + CR 564 + "fromFile=[" + fromFile + "]" + CR 565 + "toFile =[" + toFile + "]" + CR ; 566 // 6.3.8.5 (2015/10/16) StringUtil.ogErrMsgPrint 使用。 567 System.out.println( ThrowUtil.ogThrowMsg( errMsg , ex ) ); // 6.4.2.0 (2016/01/29) 568 return false; 569 } 570 finally { 571 Closer.ioClose( fromStream ) ; 572 Closer.ioClose( toStream ) ; 573 } 574 575 return true; 576 } 577 578 /** 579 * ファイルのバイナリコピーを行います。 580 * 581 * コピー元のファイルは、InputStream で指定します。 582 * 元は、jsp/common 以下を圧縮、jar化したため、物理ファイルの取得が 583 * できなくなったため、ServletContext#getServletContext() で、ローカルリソースを 584 * 取得するのが目的です。汎用的に、入力は、InputStream にしました。 585 * URLConnection 等で、取得する場合は、BASIC認証も考慮する必要がありますので、 586 * ご注意ください。 587 * タイムスタンプのコピーは行いません。 588 * 589 * @og.rev 6.3.6.1 (2015/08/28) InputStreamで指定されたファイルのコピー 590 * @og.rev 6.3.8.5 (2015/10/16) StringUtil.ogErrMsgPrint 使用。 591 * @og.rev 6.4.2.0 (2016/01/29) StringUtil#ogErrMsgPrint(String,Throwable) を、ThrowUtilt#ogThrowMsg(String,Throwable) に変更。 592 * 593 * @param inStrm コピー元のInputStream(この中でcloseします) 594 * @param toFile コピー先ファイル 595 * 596 * @return バイナリコピーが正常に終了したかどうか[true:成功/false:失敗] 597 * @see #copy( File,File ) 598 */ 599 public static boolean copy( final InputStream inStrm,final File toFile ) { 600 FileOutputStream foStrm = null; 601 try { 602 // copy先(toFile)のフォルダが存在しなければ、作成します。 603 final File parent = toFile.getParentFile(); 604 if( !parent.exists() && !parent.mkdirs() ) { 605 // ディレクトリを作成する 606 System.err.println( parent + " の ディレクトリ作成に失敗しました。" ); 607 return false; 608 } 609 610 foStrm = new FileOutputStream( toFile, false ); 611 return copy( inStrm , foStrm ); 612 } 613 catch( final IOException ex ) { 614 // 6.3.6.1 (2015/08/28) Exception発生時に return ではなく、StringUtil.ogErrMsg に変更。 615 final String errMsg = "入力ストリームのコピーでエラーが発生しました。" + CR 616 + "toFile =[" + toFile + "]" + CR ; 617 // 6.3.8.5 (2015/10/16) StringUtil.ogErrMsgPrint 使用。 618 System.out.println( ThrowUtil.ogThrowMsg( errMsg , ex ) ); // 6.4.2.0 (2016/01/29) 619 } 620 finally { 621 Closer.ioClose( inStrm ); 622 Closer.ioClose( foStrm ); 623 } 624 625 return false ; 626 } 627 628 /** 629 * 入出力ストリーム間でデータの転送を行います。 630 * 631 * ここでは、すでに作成されたストリームに基づき、データの入出力を行います。 632 * よって、先にフォルダ作成や、存在チェック、ファイルの削除などの必要な処理は 633 * 済まして置いてください。 634 * また、このメソッド内で、ストリームのクロース処理は行っていません。 635 * 636 * @og.rev 5.1.6.0 (2010/05/01) 新規追加 637 * @og.rev 6.3.6.1 (2015/08/28) エラー時のメッセージ情報を増やします。 638 * @og.rev 6.3.8.5 (2015/10/16) StringUtil#ogErrMsgPrint 使用。 639 * @og.rev 6.4.2.0 (2016/01/29) StringUtil#ogErrMsgPrint(String,Throwable) を、ThrowUtilt#ogThrowMsg(String,Throwable) に変更。 640 * 641 * @param input 入力ストリーム 642 * @param output 出力ストリーム 643 * 644 * @return データ転送が正常に終了したかどうか[true:成功/false:失敗] 645 */ 646 public static boolean copy( final InputStream input,final OutputStream output ) { 647 if( input == 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 if( output == null ) { 655 final String errMsg = "出力ストリームが 作成されていません。" ; 656 // 6.3.8.5 (2015/10/16) StringUtil.ogErrMsgPrint 使用。 657 System.out.println( ThrowUtil.ogThrowMsg( errMsg ) ); // 6.4.2.0 (2016/01/29) 658 return false; 659 } 660 661 try { 662 final byte[] buf = new byte[BUFSIZE]; 663 int len; 664 while((len = input.read(buf)) != -1) { 665 output.write(buf, 0, len); 666 } 667 } 668 catch( final IOException ex ) { 669 final String errMsg = "ストリームデータの入出力処理に失敗しました。"; 670 // 6.3.8.5 (2015/10/16) StringUtil.ogErrMsgPrint 使用。 671 System.out.println( ThrowUtil.ogThrowMsg( errMsg,ex ) ); // 6.4.2.0 (2016/01/29) 672 return false; 673 } 674 // finally { 675 // Closer.ioClose( input ); 676 // Closer.ioClose( output ); 677 // } 678 return true ; 679 } 680 681 /** 682 * 再帰処理でディレクトリのコピーを行います。 683 * 684 * 指定されたコピー元ディレクトリがディレクトリでなかったり存在しないときは falseを返します。 685 * 686 * @og.rev 4.3.0.0 (2008/07/24) 追加 687 * @og.rev 5.1.6.0 (2010/05/01) 戻り値に、true/false 指定します。 688 * 689 * @param fromDir コピー元ディレクトリ名 690 * @param toDir コピー先ディレクトリ名 691 * 692 * @return ディレクトリのコピーが正常に終了したかどうか[true:成功/false:失敗] 693 */ 694 public static boolean copyDirectry( final String fromDir, final String toDir ) { 695 return copyDirectry( new File( fromDir ), new File( toDir ),false ); 696 } 697 698 /** 699 * 再帰処理でディレクトリをコピーします。 700 * 701 * 指定されたコピー元ディレクトリがディレクトリでなかったり存在しないときは falseを返します。 702 * 703 * @og.rev 4.3.0.0 (2008/07/24) 追加 704 * @og.rev 5.1.6.0 (2010/05/01) 内部処理を若干変更します。 705 * 706 * @param fromDir コピー元ディレクトリ 707 * @param toDir コピー先ディレクトリ 708 * 709 * @return ディレクトリのコピーが正常に終了したかどうか[true:成功/false:失敗] 710 */ 711 public static boolean copyDirectry( final File fromDir, final File toDir ) { 712 return copyDirectry( fromDir, toDir, false ); 713 } 714 715 /** 716 * 再帰処理でディレクトリをコピーします。 717 * 718 * 指定されたコピー元ディレクトリがディレクトリでなかったり存在しないときは falseを返します。 719 * 720 * @og.rev 4.3.0.0 (2008/07/24) 追加 721 * @og.rev 5.1.6.0 (2010/05/01) 内部処理を若干変更します。 722 * @og.rev 5.3.7.0 (2011/07/01) フォルダにアクセスできない場合は、エラーを返します。 723 * 724 * @param fromDir コピー元ディレクトリ 725 * @param toDir コピー先ディレクトリ 726 * @param keepTimeStamp タイムスタンプ維持[true/false] 727 * 728 * @return ディレクトリのコピーが正常に終了したかどうか[true:成功/false:失敗] 729 */ 730 public static boolean copyDirectry( final File fromDir, final File toDir, final boolean keepTimeStamp ) { 731 // コピー元がディレクトリでない場合はfalseを返す 732 // 4.3.4.4 (2009/01/01) 733 if( !fromDir.exists() || !fromDir.isDirectory() ) { 734 System.err.println( fromDir + " が ディレクトリでないか、存在しません。" ); 735 return false; 736 } 737 738 // 4.3.4.4 (2009/01/01) ディレクトリを作成する 739 // 6.0.0.1 (2014/04/25) These nested if statements could be combined 740 if( !toDir.exists() && !toDir.mkdirs() ) { 741 System.err.println( toDir + " の ディレクトリ作成に失敗しました。" ); 742 return false; 743 } 744 745 // ディレクトリ内のファイルをすべて取得する 746 final File[] files = fromDir.listFiles(); 747 748 // 5.3.7.0 (2011/07/01) フォルダにアクセスできない場合は、エラー 749 if( files == null ) { 750 System.err.println( fromDir + " はアクセスできません。" ); 751 return false; 752 } 753 754 // ディレクトリ内のファイルに対しコピー処理を行う 755 boolean flag = true; 756 for( int i=0; files.length>i; i++ ){ 757 if( files[i].isDirectory() ){ // ディレクトリだった場合は再帰呼び出しを行う 758 flag = copyDirectry( files[i], new File( toDir, files[i].getName()),keepTimeStamp ); 759 } 760 else{ // ファイルだった場合はファイルコピー処理を行う 761 flag = copy( files[i], new File( toDir, files[i].getName()),keepTimeStamp ); 762 } 763 if( !flag ) { return false; } 764 } 765 return true; 766 } 767 768 /** 769 * 指定されたファイル及びディレクトを削除します。 770 * ディレクトリの場合はサブフォルダ及びファイルも削除します。 771 * 1つでもファイルの削除に失敗した場合、その時点で処理を中断しfalseを返します。 772 * 773 * @og.rev 5.3.7.0 (2011/07/01) フォルダにアクセスできない場合は、エラーを返します。 774 * 775 * @param file 削除ファイル/ディレクトリ 776 * 777 * @return ファイル/ディレクトリの削除に終了したかどうか[true:成功/false:失敗] 778 */ 779 public static boolean deleteFiles( final File file ) { 780 if( file.exists() ) { 781 if( file.isDirectory() ) { 782 final File[] list = file.listFiles(); 783 784 // 5.3.7.0 (2011/07/01) フォルダにアクセスできない場合は、エラー 785 if( list == null ) { 786 System.err.println( file + " はアクセスできません。" ); 787 return false; 788 } 789 790 for( int i=0; i<list.length; i++ ) { 791 deleteFiles( list[i] ); 792 } 793 } 794 if( !file.delete() ) { return false; } 795 } 796 return true; 797 } 798 799 /** 800 * 指定されたディレクトリを基点としたファイル名(パスを含む)の一覧を返します。 801 * 互換性のため、コピー中ファイルも含みます。 802 * 803 * @og.rev 5.4.3.2 (2012/01/06) コピー中対応のため引数4つを作成する 804 * 805 * @param dir 基点となるディレクトリ 806 * @param sort ファイル名でソートするか 807 * @param list ファイル名一覧を格納するList 808 */ 809 public static void getFileList( final File dir, final boolean sort, final List<String> list ) { 810// getFileList( dir, sort, list, true ); 811 getFileList( dir, null, sort, list, true ); // 7.0.1.4 (2018/11/26) FileFilter を利用 812 } 813 814 /** 815 * 指定されたディレクトリを基点としたファイル名(パスを含む)の一覧を返します。 816 * 817 * @og.rev 4.3.6.6 (2009/05/15) 新規作成 818 * @og.rev 5.4.3.2 (2012/01/06) 引数isCopy追加 819 * @og.rev 6.3.9.0 (2015/11/06) null になっている可能性があるメソッドの戻り値のnullチェックを追加。 820 * 821 * @param dir 基点となるディレクトリ 822 * @param sort ファイル名でソートするか 823 * @param list ファイル名一覧を格納するList 824 * @param isCopy コピー中ファイルを除外するか [true:含む/false:除外] 825 */ 826 public static void getFileList( final File dir, final boolean sort, final List<String> list, final boolean isCopy ) { 827 getFileList( dir, null, sort, list, true ); // 7.0.1.4 (2018/11/26) FileFilter を利用 828 829// if( list == null ) { return; } 830// if( dir.isFile() ) { 831// // コピー中判定はrenameで行う 832// // 6.1.0.0 (2014/12/26) refactoring : Avoid if(x != y) ..; else ..; 833// if( isCopy || dir.renameTo( dir ) ) { 834// list.add( dir.getAbsolutePath() ); 835// } 836// else{ 837// return; 838// } 839// } 840// else if( dir.isDirectory() ) { 841// final File[] files = dir.listFiles(); 842// // 6.3.9.0 (2015/11/06) null になっている可能性があるメソッドの戻り値のnullチェックを追加。 843// if( files != null ) { 844// for( int i=0; i<files.length; i++ ) { 845// getFileList( files[i], sort, list, isCopy ); 846// } 847// } 848// } 849// if( sort ) { 850// Collections.sort( list ); 851// } 852 } 853 854 /** 855 * 指定されたディレクトリを基点としたファイル名(パスを含む)の一覧を返します。 856 * 857 * @og.rev 4.3.6.6 (2009/05/15) 新規作成 858 * @og.rev 5.4.3.2 (2012/01/06) 引数isCopy追加 859 * @og.rev 6.3.9.0 (2015/11/06) null になっている可能性があるメソッドの戻り値のnullチェックを追加。 860 * @og.rev 7.0.1.4 (2018/11/26) FileFilter を利用して、フォルダの絞り込みを行う。 861 * 862 * @param dir 基点となるディレクトリ 863 * @param filter ディレクトリやファイルを絞り込むフィルター(nullの場合は、すべてOK) 864 * @param sort ファイル名でソートするか 865 * @param list ファイル名一覧を格納するList 866 * @param isCopy コピー中ファイルを除外するか [true:含む/false:除外] 867 */ 868 public static void getFileList( final File dir, final FileFilter filter, final boolean sort, final List<String> list, final boolean isCopy ) { 869 if( list == null ) { return; } 870 if( dir.isFile() ) { 871 // コピー中判定はrenameで行う 872 // 6.1.0.0 (2014/12/26) refactoring : Avoid if(x != y) ..; else ..; 873 if( isCopy || dir.renameTo( dir ) ) { 874 list.add( dir.getAbsolutePath() ); 875 } 876 else{ 877 return; 878 } 879 } 880 else if( dir.isDirectory() ) { 881// final File[] files = dir.listFiles(); 882 final File[] files = dir.listFiles( filter ); 883 // 6.3.9.0 (2015/11/06) null になっている可能性があるメソッドの戻り値のnullチェックを追加。 884 if( files != null ) { 885 for( int i=0; i<files.length; i++ ) { 886 getFileList( files[i], sort, list, isCopy ); 887 } 888 } 889 } 890 if( sort ) { 891 Collections.sort( list ); 892 } 893 } 894 895 /** 896 * ファイルをリネームを行います。 897 * 引数のuseBackup属性を true にすると、toFile が存在した場合、toFile の直下に "_backup" フォルダを 898 * 作成して、toFile + "_" + (現在時刻のLONG値) + "." + (toFileの拡張子) に名前変更します。 899 * useBackup属性を rename にすると、toFile が存在した場合、toFile に、"_001" からなる 900 * 連番を付与し、重複しなくなるまで、名前を変更します。 901 * useBackup属性を false(またはnull) にすると、toFile が存在した場合、toFile を削除します。 902 * 903 * 戻り値は、変更後のファイルオブジェクトです。 904 * 905 * @og.rev 5.7.1.2 (2013/12/20) 新規追加 906 * @og.rev 6.0.2.4 (2014/10/17) useBackup の機能追加 907 * @og.rev 6.2.0.0 (2015/02/27) FileInfoクラスを使用。 (#getFileSplit(File)の結果配列は廃止) 908 * @og.rev 5.9.10.0 (2019/03/01) FileOperation対応 909 * @og.rev 8.0.0.1 (2021/10/08) クラウド修正 910 * 911 * @param fromFile 名前変更する元のファイル 912 * @param toFile 名前変更後のファイル 913 * @param useBackup 置き換えファイルの処理方法(true:backupフォルダ/false:しない/rename:重複しない連番) 914 * @return 名前変更後のファイル 915 * @throws RuntimeException 名称変更処理ができなかった場合。 916 */ 917 public static File renameTo( final File fromFile , final File toFile , final String useBackup ) { 918 if( fromFile == null || toFile == null ) { 919 final String errMsg = "入力ファイルが null です。from=[" + fromFile + "] , to=[" + toFile + "]" ; 920 throw new OgRuntimeException( errMsg ); 921 } 922 923 final File parent = toFile.getParentFile(); // 6.0.2.4 (2014/10/17) toFile のフォルダがなければ作成 924 if( !parent.exists() && !parent.mkdirs() ) { 925 final String errMsg = "toファイルのフォルダが作成できません。from=[" + fromFile + "] , to=[" + toFile + "]" ; 926 throw new OgRuntimeException( errMsg ); 927 } 928 929 // 変更先のファイルが存在した場合の処理。 930 File newFile = toFile; // useBackup = "rename" の時のみ書き換えたいので。 931 if( toFile.exists() ) { 932 final FileInfo info = new FileInfo( toFile ); // 6.2.0.0 (2015/02/27) 933 // バックアップ作成する場合 934 // 6.0.2.4 (2014/10/17) useBackup は、文字列で、true/false,(null)/rename がある。 935 if( "true".equalsIgnoreCase( useBackup ) ) { 936// final File backup = new File( parent , "_backup" ); // その直下に、"_backup" フォルダを作成 937 // 8.0.0.1 (2021/10/08) クラウド修正 938// final File backup = FileOperationFactory.newStorageOperation(toFile, parent.getPath(), "_backup"); // 5.10.9.0 (2019/03/01) 939 final File backup = FileOperationFactory.resolveFile(toFile, parent.getPath(), "_backup"); // 5.10.9.0 (2019/03/01) 940 if( !backup.exists() && !backup.mkdirs() ) { 941 final String errMsg = "バックアップ処理でbackupフォルダの作成に失敗しました。[" + backup + "]"; 942 throw new OgRuntimeException( errMsg ); 943 } 944 // バックアップファイル名は、元のファイル名(拡張子含む) + "_" + 現在時刻のlong値 + "." + 元のファイルの拡張子 945 final String toName = toFile.getName(); 946// final File toFile2 = new File( parent,toName ); // オリジナルの toFile をrename するとまずいので、同名のFileオブジェクトを作成 947 // 8.0.0.1 (2021/10/08) クラウド修正 948// final File toFile2 = FileOperationFactory.newStorageOperation(toFile, parent.getPath(), toName); // 5.10.9.0 (2019/03/01) 949 final File toFile2 = FileOperationFactory.resolveFile(toFile, parent.getPath(), toName); // 5.10.9.0 (2019/03/01) 950 951 final String bkupName = info.NAME + "_" + System.currentTimeMillis() + "." + info.SUFIX ; // 6.2.0.0 (2015/02/27) 952// final File bkupFile = new File( backup,bkupName ); 953 // 8.0.0.1 (2021/10/08) クラウド修正 954// final File bkupFile = FileOperationFactory.newStorageOperation(backup, backup.getParent(), bkupName); // 5.10.9.0 (2019/03/01) 955 final File bkupFile = FileOperationFactory.resolveFile(backup, backup.getParent(), bkupName); // 5.10.9.0 (2019/03/01) 956 957 if( !toFile2.renameTo( bkupFile ) ) { 958 final String errMsg = "バックアップ処理でバックアップファイルをリネームできませんでした。" +CR 959 + " [" + toFile + "] ⇒ [" + bkupFile + "]" ; 960 throw new OgRuntimeException( errMsg ); 961 } 962 } 963 // 他と違い、toFile を変更する必要がある。 964 else if( "rename".equalsIgnoreCase( useBackup ) ) { 965 for( int i=1000; i<2000; i++ ) { // 000 の3桁を取得したいため。 966 final String no = String.valueOf( i ).substring(1); 967 // 6.2.0.0 (2015/02/27) 配列ではなく、FileInfoクラスを使用 968// final File toFile2 = new File( info.DIR , info.NAME + "_" + no + "." + info.SUFIX ); 969 // 8.0.0.1 (2021/10/08) クラウド修正 970// final File toFile2 = FileOperationFactory.newStorageOperation(toFile, info.DIR, info.NAME + "_" + no + "." + info.SUFIX); // 5.10.9.0 (2019/03/01) 971 final File toFile2 = FileOperationFactory.resolveFile(toFile, info.DIR, info.NAME + "_" + no + "." + info.SUFIX); // 5.10.9.0 (2019/03/01) 972 if( !toFile2.exists() ) { 973 newFile = toFile2; 974 break; 975 } 976 } 977 } 978 // バックアップ作成しない場合は、削除します。 979 else if( !toFile.delete() ) { 980 final String errMsg = "既存のファイル[" + toFile + "]が削除できませんでした。"; 981 throw new OgRuntimeException( errMsg ); 982 } 983 } 984 985 if( !fromFile.renameTo( newFile ) ) { 986 final String errMsg = "所定のファイルをリネームできませんでした。" + CR 987 + " [" + fromFile + "] ⇒ [" + newFile + "]" ; 988 throw new OgRuntimeException( errMsg ); 989 } 990 return newFile; 991 } 992 993 /** 994 * ファイルを読み取って、文字列を作成します。 995 * 996 * データの読取が完全に出来なかったときには、途中までのデータを返します。 997 * 指定のエンコードが存在しない場合や、ファイルが存在しない場合は、 998 * OgRuntimeException を throw します。 999 * encode が null の場合は、UTF-8 で読み込みます。 1000 * 1001 * @og.rev 6.4.2.0 (2016/01/29) fukurou.util.StringUtil → fukurou.system.HybsConst に変更 1002 * @og.rev 6.4.5.1 (2016/04/28) encode は初期化しているため、null はセットされません。 1003 * @og.rev 6.4.5.2 (2016/05/06) fukurou.util.FileString から、fukurou.util.FileUtil に移動。 1004 * 1005 * @param filename ファイル名 1006 * @param encode エンコード名 1007 * @return ファイルを読み取った文字列 1008 * @throws RuntimeException 指定のエンコードが存在しなかったとき。 1009 */ 1010 public static String getValue( final String filename , final String encode ) { 1011 if( filename == null ) { 1012 final String errMsg = "ファイル名が指定されていません。" ; 1013 throw new OgRuntimeException( errMsg ); 1014 } 1015 1016 final String enc = encode == null ? HybsConst.UTF_8 : encode ; 1017 1018 try { 1019 return new String( Files.readAllBytes( new File( filename ).toPath() ),enc ); 1020 } 1021 catch( final IOException ex ) { 1022 final String errMsg = "ファイル名がオープン出来ませんでした。[" + filename + "]" ; 1023 throw new OgRuntimeException( errMsg,ex ); 1024 } 1025 } 1026 1027 /** 1028 * 改行コードで分割して、Listオブジェクトを返します。 1029 * 1030 * encode が null の場合は、UTF-8 で読み込みます。 1031 * 1032 * @og.rev 6.4.5.2 (2016/05/06) fukurou.util.FileString から、fukurou.util.FileUtil に移動。 1033 * 1034 * @param filename ファイル名 1035 * @param encode エンコード名 1036 * @return ファイルを読み取った文字列を分割したList 1037 */ 1038 public static List<String> getLineList( final String filename , final String encode ) { 1039 try { 1040 final String enc = encode == null ? HybsConst.UTF_8 : encode ; 1041 1042 return Files.readAllLines( new File( filename ).toPath() , Charset.forName( enc ) ); 1043 } 1044 catch( final IOException ex ) { 1045 final String errMsg = "ファイル名がオープン出来ませんでした。[" + filename + "]" ; 1046 throw new OgRuntimeException( errMsg,ex ); 1047 } 1048 } 1049 1050 /** 1051 * Fileオブジェクトのサイズを返します。 1052 * 1053 * オブジェクトが通常のファイルの場合は、そのファイルサイズを返します。 1054 * フォルダの場合は、再帰的に、ファイルサイズを加算した結果を返します。 1055 * 1056 * @og.rev 6.7.4.1 (2017/02/17) Fileオブジェクトのサイズを返します。 1057 * 1058 * @param file Fileオブジェクト 1059 * @return ファイルまたはフォルダののサイズ 1060 */ 1061 public static long length( final File file ) { 1062 if( file.isDirectory() ) { 1063 final File[] children = file.listFiles(); 1064 1065 long sum = 0; 1066 if( children != null ) { 1067 for( final File child : children ) { 1068 sum += length( child ); 1069 } 1070 } 1071 return sum; 1072 } 1073 return file.length(); 1074 } 1075 1076 /** 1077 * PrintWriter を継承した、System.out/System.err 用のクラスを定義します。 1078 * 1079 * 通常の、new PrintWriter( OutputStream ) で、求めるのと、ほとんど同様の 1080 * 処理を行います。 1081 * ただ、close() メソッドが呼ばれても、何もしません。 1082 * 1083 */ 1084 private static final class NonClosePrintWriter extends PrintWriter { 1085 /** 1086 * コンストラクター 1087 * 1088 * new PrintWriter( OutputStream ) を行います。 1089 * 1090 * @param out OutputStreamオブジェクト 1091 */ 1092 public NonClosePrintWriter( final OutputStream out ) { 1093 super( out ); 1094 } 1095 1096 /** 1097 * close() メソッドをオーバーライドします。 1098 * 1099 * 何もしません。 1100 */ 1101 @Override 1102 public void close() { 1103 // ここでは処理を行いません。 1104 } 1105 } 1106 1107 /** 1108 * PrintWriter を継承した、JspWriterなどの Writer 用のクラスを定義します。 1109 * 1110 * 例えば、JspWriterなどの JSP/Servlet等のフレームワークで使用される 1111 * Writer では、flush や close 処理は、フレームワーク内で行われます。 1112 * その場合、通常のファイルと同じ用に、flush や close をアプリケーション側で 1113 * 行うと、内部処理的に不整合が発生したり、最悪の場合エラーになります。 1114 * このクラスは、単に、通常の、new PrintWriter( Writer ) で、求めるのと、 1115 * ほとんど同様の処理を行います。 1116 * ただ、close() と flush() メソッドが呼ばれても、何もしません。 1117 * 1118 */ 1119 private static final class NonFlushPrintWriter extends PrintWriter { 1120 /** 1121 * コンストラクター 1122 * 1123 * new PrintWriter( Writer ) を行います。 1124 * 1125 * @param writer Writerオブジェクト 1126 */ 1127 public NonFlushPrintWriter( final Writer writer ) { 1128 super( writer ); 1129 } 1130 1131 /** 1132 * close() メソッドをオーバーライドします。 1133 * 1134 * 何もしません。 1135 */ 1136 @Override 1137 public void close() { 1138 // ここでは処理を行いません。 1139 } 1140 1141 /** 1142 * flush() メソッドをオーバーライドします。 1143 * 1144 * 何もしません。 1145 */ 1146 @Override 1147 public void flush() { 1148 // ここでは処理を行いません。 1149 } 1150 } 1151 1152 /** 1153 * ファイルのエンコードを変換するコピーを行います。 1154 * 1155 * copy( File,File,false ) を呼び出します。 1156 * 1157 * @og.rev 5.1.6.0 (2010/05/01) 戻り値に、true/false 指定します。 1158 * 1159 * @param file1 コピー元ファイル名 1160 * @param file2 コピー先ファイル名 1161 * @param encode1 コピー元ファイルのエンコード 1162 * @param encode2 コピー先ファイルのエンコード 1163 * 1164 * @see #copy( File,File,boolean ) 1165 */ 1166 public static void copy( final File file1,final File file2,final String encode1,final String encode2 ) { 1167 // final File tempFile = new File( file2.getName() + "_backup" ); 1168 1169 // FileUtil.copy( file2,tempFile ); 1170 1171 final BufferedReader reader = FileUtil.getBufferedReader( file1 ,encode1 ); 1172 final PrintWriter writer = FileUtil.getPrintWriter( file2 ,encode2 ); 1173 1174 try { 1175 String line1; 1176 while((line1 = reader.readLine()) != null) { 1177 writer.println( line1 ); 1178 } 1179 } 1180 catch( final Throwable th ) { 1181 th.printStackTrace(); 1182 } 1183 finally { 1184 Closer.ioClose( reader ) ; 1185 Closer.ioClose( writer ) ; 1186 } 1187 1188 // 6.9.8.0 (2018/05/28) FindBugs:例外的戻り値を無視しているメソッド 1189// file2.setLastModified( file1.lastModified() ); 1190 if( !file2.setLastModified( file1.lastModified() ) ) { 1191 final String errMsg = "FileUtil.copy において、タイムスタンプの更新が出来ませんでした。" + CR 1192 + " file2= [" + file2 + "]" + CR ; 1193 System.err.println( errMsg ); 1194 } 1195 } 1196 1197 /** 1198 * ファイルをコピーします。 1199 * 1200 * 引数に <file1> <file2> [<encode1> <encode2>] を指定します。 1201 * file1 を読み込み、file2 にコピーします。コピー前に、file2 は、file2_backup にコピーします。 1202 * file1 が、ディレクトリの場合は、ディレクトリごとコピーします。 1203 * encode1、encode2 を指定すると、エンコード変換しながらコピーになります。 1204 * この場合は、ファイル同士のコピーのみになります。 1205 * 1206 * @og.rev 4.0.0.0 (2007/11/28) メソッドの戻り値をチェックします。 1207 * @og.rev 5.1.6.0 (2010/05/01) 引数の並び順、処理を変更します。 1208 * 1209 * @param args 引数配列 file1 file2 [encode1 encode2] 1210 * @throws Throwable なんらかのエラーが発生した場合。 1211 */ 1212 public static void main( final String[] args ) throws Throwable { 1213 if( args.length != 2 && args.length != 4 ) { 1214 LogWriter.log("Usage: java org.opengion.fukurou.util.FileUtil <file1> <file2> [<encode1> <encode2>]" ); 1215 return ; 1216 } 1217 1218 final File file1 = new File( args[0] ); 1219 final File file2 = new File( args[1] ); 1220 1221 if( args.length < 3 ) { 1222 if( file1.isDirectory() ) { 1223 FileUtil.copyDirectry( file1, file2, true ); 1224 } 1225 else { 1226 final File tempFile = new File( args[1] + "_backup" ); 1227 FileUtil.copy( file2,tempFile ); 1228 FileUtil.copy( file1,file2, true ); 1229 } 1230 } 1231 else { 1232 final String encode1 = args[2]; 1233 final String encode2 = args[3]; 1234 1235 if( file1.isDirectory() ) { 1236 final File[] children = file1.listFiles(); 1237 1238 if( children != null ) { 1239 for( final File child : children ) { 1240 copy( child , new File( file2 , child.getName() ),encode1,encode2 ); 1241 } 1242 } 1243 } 1244 else { 1245 copy( file1,file2,encode1,encode2 ); 1246 } 1247 } 1248 } 1249}