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