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     */
016    package org.opengion.fukurou.util;
017    
018    import java.io.BufferedInputStream;
019    import java.io.BufferedOutputStream;
020    import java.io.BufferedReader;
021    import java.io.BufferedWriter;
022    import java.io.File;
023    import java.io.InputStream;
024    import java.io.FileInputStream;
025    import java.io.FileNotFoundException;
026    import java.io.FileOutputStream;
027    import java.io.IOException;
028    import java.io.InputStreamReader;
029    import java.io.OutputStream;
030    import java.io.OutputStreamWriter;
031    import java.io.PrintWriter;
032    import java.io.UnsupportedEncodingException;
033    import java.io.Writer;
034    import java.util.Collections;
035    import java.util.List;
036    
037    // import java.nio.ByteBuffer;
038    import java.nio.channels.FileChannel;
039    
040    /**
041     * FileUtil.java は、å?通的に使用されã‚?File関連メソãƒ?ƒ‰を集ç´?�—たã?クラスですã?
042     *
043     * 全変数は、public static final 宣è¨?�•れており、å?メソãƒ?ƒ‰は、public static synchronized 宣è¨?�•れてã�?�¾すã?
044     *
045     * @og.group ユーãƒ?‚£リãƒ?‚£
046     *
047     * @version  4.0
048     * @author       Kazuhiko Hasegawa
049     * @since    JDK5.0,
050     */
051    public final class FileUtil {
052            private static final NonClosePrintWriter outWriter = new NonClosePrintWriter( System.out );
053            private static final NonClosePrintWriter errWriter = new NonClosePrintWriter( System.err );
054    
055            /**
056             * すべてã�?staticメソãƒ?ƒ‰なので、コンストラクタを呼び出さなくしておきますã?
057             *
058             */
059            private FileUtil() {}
060    
061            /** シスãƒ?ƒ 依存ã?改行記号をセãƒ?ƒˆしますã?     */
062            private static final String CR = System.getProperty("line.separator");
063    
064            /** 5.6.1.2 (2013/02/22) UNIX系のファイル名を表すセパレータæ–?­?*/
065            private static final char UNIX_SEPARATOR = '/';
066    
067            /** 5.6.1.2 (2013/02/22) Windwos系のファイル名を表すセパレータæ–?­?*/
068            private static final char WINDOWS_SEPARATOR = '\\';
069    
070            /** 5.6.1.2 (2013/02/22) ファイルの拡張子ã?区åˆ?‚Šを表す文å­?*/
071            public static final char EXTENSION_SEPARATOR = '.';
072    
073            /**
074             * Fileオブジェクトとエンコードよã‚?PrintWriterオブジェクトを作æ?しますã?
075             *
076             * @param       file    出力するファイルオブジェクãƒ?
077             * @param       encode  ファイルのエンコーãƒ?
078             *
079             * @return      PrintWriterオブジェクãƒ?
080             * @throws RuntimeException 何らかã?エラーが発生したå?å�?
081             */
082            public static PrintWriter getPrintWriter( final File file,final String encode ) {
083                    return getPrintWriter( file,encode,false );
084            }
085    
086            /**
087             * Fileオブジェクトとエンコードよã‚?PrintWriterオブジェクトを作æ?しますã?
088             *
089             * @param       file    出力するファイルオブジェクãƒ?
090             * @param       encode  ファイルのエンコーãƒ?
091             * @param       append  ファイルを追åŠ?ƒ¢ーãƒ?true)にするかどã�?�‹
092             *
093             * @return      PrintWriterオブジェクãƒ?
094             * @throws RuntimeException 何らかã?エラーが発生したå?å�?
095             */
096            public static PrintWriter getPrintWriter( final File file,final String encode,final boolean append ) {
097                    final PrintWriter writer ;
098    
099                    try {
100                            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
101                                            new FileOutputStream(file,append) ,encode )));
102                    }
103                    catch( UnsupportedEncodingException ex ) {
104                            String errMsg = "æŒ?®šされたエンコーãƒ?‚£ングがサポã?トされてã�?�¾せんã€? + CR
105                                                            + ex.getMessage() + CR
106                                                            + "File=[" + file + " , encode=[" + encode + "]" ;
107                            throw new RuntimeException( errMsg,ex );
108                    }
109                    catch( FileNotFoundException ex ) {             // 3.6.1.0 (2005/01/05)
110                            String errMsg = "ファイル名がオープン出来ませんでしたã€? + CR
111                                                            + ex.getMessage() + CR
112                                                            + "File=[" + file + " , encode=[" + encode + "]" ;
113                            throw new RuntimeException( errMsg,ex );
114                    }
115    
116                    return writer ;
117            }
118    
119            /**
120             * ファイル名よりã?PrintWriterオブジェクトを作æ?する簡易メソãƒ?ƒ‰ですã?
121             *
122             * これは、ファイル名ã?、フルパスで、追åŠ?ƒ¢ードで、UTF-8 エンコードã?
123             * ログファイルをå?力するå?合に使用しますã?
124             * またã?ファイル名にã€?System.out" とã€?System.err" を指定できますã?
125             * そã?場合ã?、標準å?力ã?またã?、標準エラー出力に出力されますã?
126             * "System.out" とã€?System.err" を指定したå?合ã?、NonClosePrintWriter
127             * オブジェクトが返されますã?これは、close() 処ç�?�Œ呼ばれてもã?何もしなã�?
128             * クラスですã?またã?常にå†?ƒ¨キャãƒ?‚·ュの同じオブジェクトが返されますã?
129             *
130             * @param       file    出力するファイルå�?
131             *
132             * @return      PrintWriterオブジェクãƒ?
133             * @throws RuntimeException 何らかã?エラーが発生したå?å�?
134             * @throws IllegalArgumentException ファイル名が null の場å�?
135             */
136            public static PrintWriter getLogWriter( final String file ) {
137                    if( file == null ) {
138                            String errMsg = "ファイル名に、null はæŒ?®šできませんã€?;
139                            throw new IllegalArgumentException( errMsg );
140                    }
141    
142                    final PrintWriter writer ;
143                    if( "System.out".equalsIgnoreCase( file ) ) {
144                            writer = outWriter ;
145                    }
146                    else if( "System.err".equalsIgnoreCase( file ) ) {
147                            writer = errWriter ;
148                    }
149                    else {
150                            writer = getPrintWriter( new File( file ),"UTF-8",true );
151                    }
152    
153                    return writer ;
154            }
155    
156            /**
157             * OutputStreamとエンコードよã‚?PrintWriterオブジェクトを作æ?しますã?
158             *
159             * @og.rev 5.5.2.0 (2012/05/01) 新規追åŠ?
160             *
161             * @param       os              利用するOutputStream
162             * @param       encode  ファイルのエンコーãƒ?
163             *
164             * @return      PrintWriterオブジェクãƒ?
165             * @throws RuntimeException 何らかã?エラーが発生したå?å�?
166             */
167            public static PrintWriter getPrintWriter( final OutputStream os,final String encode ) {
168                    final PrintWriter writer ;
169    
170                    try {
171                            writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
172                                            os ,encode )));
173                    }
174                    catch( UnsupportedEncodingException ex ) {
175                            String errMsg = "æŒ?®šされたエンコーãƒ?‚£ングがサポã?トされてã�?�¾せんã€? + CR
176                                                            + ex.getMessage() + CR
177                                                            + "encode=[" + encode + "]" ;
178                            throw new RuntimeException( errMsg,ex );
179                    }
180                    return writer ;
181            }
182    
183            /**
184             * PrintWriter を継承した、JspWriterなどの Writer 用のクラスを定義しますã?
185             *
186             * 例えば、JspWriterなどの JSP/Servlet等ã?フレーãƒ?ƒ¯ークで使用されã‚?
187             * Writer では、flush ã‚?close 処ç�??、フレーãƒ?ƒ¯ークå†?�§行われますã?
188             * そã?場合ã?通常のファイルと同じ用に、flush ã‚?close をアプリケーション側で
189             * 行うと、å?部処ç�?š„に不整合が発生したり、最悪の場合エラーになりますã?
190             * こã?クラスは、NonFlushPrintWriter クラスのオブジェクトを返しますã?
191             * これはã€??常の、new PrintWriter( Writer ) で、求めるã?と、ほとんど同様ã?
192             * 処ç�?‚’行いますが、close() と flush() メソãƒ?ƒ‰が呼ばれてもã?何もしませんã€?
193             *
194             * @param       writer  出力するWriteオブジェクãƒ?NonFlushPrintWriterクラス)
195             *
196             * @return      PrintWriterオブジェクãƒ?
197             */
198            public static PrintWriter getNonFlushPrintWriter( final Writer writer ) {
199                    return new NonFlushPrintWriter( writer );
200            }
201    
202            /**
203             * Fileオブジェクトとエンコードよã‚?BufferedReaderオブジェクトを作æ?しますã?
204             *
205             * @param       file    入力するファイルオブジェクãƒ?
206             * @param       encode  ファイルのエンコーãƒ?
207             *
208             * @return      BufferedReaderオブジェクãƒ?
209             * @throws RuntimeException 何らかã?エラーが発生したå?å�?
210             */
211            public static BufferedReader getBufferedReader( final File file,final String encode ) {
212                    final BufferedReader reader ;
213    
214                    try {
215                            reader = new BufferedReader(new InputStreamReader(
216                                                            new FileInputStream( file ) ,encode ));
217                    }
218                    catch( UnsupportedEncodingException ex ) {
219                            String errMsg = "æŒ?®šされたエンコーãƒ?‚£ングがサポã?トされてã�?�¾せんã€? + CR
220                                                            + ex.getMessage() + CR
221                                                            + "FIle=[" + file + " , encode=[" + encode + "]" ;
222                            throw new RuntimeException( errMsg,ex );
223                    }
224                    catch( FileNotFoundException ex ) {
225                            String errMsg = "ファイル名がオープン出来ませんでしたã€? + CR
226                                                            + ex.getMessage() + CR
227                                                            + "FIle=[" + file + " , encode=[" + encode + "]" ;
228                            throw new RuntimeException( errMsg,ex );
229                    }
230    
231                    return reader ;
232            }
233    
234            /**
235             * æŒ?®šã?ファイル名が、実際に存在してã�?‚‹かどã�?�‹をチェãƒ?‚¯しますã?
236             * 存在しなã�??合ã?ã€?¼’秒毎にã€?¼“回確認しますã?
237             * それでも存在しなã�??合ã?、エラーを返しますã?
238             * return されるFileオブジェクトã?、正規ã?形å¼?CanonicalFile)ですã?
239             *
240             * @param       dir                     フォルãƒ?��
241             * @param       filename        ファイルå�?
242             *
243             * @return      存在チェãƒ?‚¯(なければ null/あれば、CanonicalFile)
244             */
245            public static File checkFile( final String dir, final String filename ) {
246                    return checkFile( dir,filename,3 );
247            }
248    
249            /**
250             * æŒ?®šã?ファイル名が、実際に存在してã�?‚‹かどã�?�‹をチェãƒ?‚¯しますã?
251             * 存在しなã�??合ã?ã€?¼’秒毎に、指定ã?回数åˆ?¢º認しますã?
252             * それでも存在しなã�??合ã?、エラーを返しますã?
253             * return されるFileオブジェクトã?、正規ã?形å¼?CanonicalFile)ですã?
254             *
255             * @param       dir                     フォルãƒ?��
256             * @param       filename        ファイルå�?
257             * @param       count           回数æŒ?®?
258             *
259             * @return      存在チェãƒ?‚¯(なければ null/あれば、CanonicalFile)
260             */
261            public static File checkFile( final String dir, final String filename,final int count ) {
262                    File file = null;
263    
264                    int cnt = count;
265                    while( cnt > 0 ) {
266                            file = new File( dir,filename );
267                            if( file.exists() ) { break; }
268                            else {
269                                    if( cnt == 1 ) { return null; }         // 残り?‘回の場合ã?ã€?¼’秒å¾?©Ÿせずに即抜けるã?
270                                    try { Thread.sleep( 2000 );     }       // ?’秒å¾?©?
271                                    catch ( InterruptedException ex ) {
272                                            System.out.println( "InterruptedException" );
273                                    }
274                                    System.out.println();
275                                    System.out.print( "CHECK File Error! CNT=" + cnt );
276                                    System.out.print( " File=" + file.getAbsolutePath() );
277                            }
278                            cnt--;
279                    }
280    
281                    // ファイルの正式パス名ã?取å¾?
282                    try {
283                            return file.getCanonicalFile() ;
284                    }
285                    catch( IOException ex ) {
286                            String errMsg = "ファイルの正式パス名が取得できませんã€?" + file.getAbsolutePath() + "]";
287                            throw new RuntimeException( errMsg,ex );
288                    }
289            }
290    
291            /**
292             * ファイルのバイナリコピã?を行いますã?
293             *
294             * copy( File,File,false ) を呼び出しますã?
295             *
296             * @og.rev 5.1.6.0 (2010/05/01) 戻りå?に、true/false æŒ?®šしますã?
297             *
298             * @param       fromFile        コピã?å…?ƒ•ァイルå�?
299             * @param       toFile          コピã?先ファイルå�?
300             *
301             * @return      バイナリコピã?が正常に終äº?�—たかどã�?�‹[true:成功/false:失敗]
302             * @see         #copy( File,File,boolean )
303             */
304            public static boolean copy( final String fromFile,final String toFile ) {
305                    return copy( new File( fromFile ), new File( toFile ), false );
306            }
307    
308            /**
309             * ファイルのバイナリコピã?を行いますã?
310             *
311             * copy( File,File,boolean ) を呼び出しますã?
312             * 第?“引数の、keepTimeStamp=true で、コピã?å…??ファイルのタイãƒ?‚¹タンプをã€?
313             * コピã?先にもセãƒ?ƒˆしますã?
314             *
315             * @og.rev 5.1.6.0 (2010/05/01) 戻りå?に、true/false æŒ?®šしますã?
316             *
317             * @param       fromFile        コピã?å…?ƒ•ァイルå�?
318             * @param       toFile          コピã?先ファイルå�?
319             * @param       keepTimeStamp   タイãƒ?‚¹タンプ維持[true/false]
320             *
321             * @return      バイナリコピã?が正常に終äº?�—たかどã�?�‹[true:成功/false:失敗]
322             * @see         #copy( File,File,boolean )
323             */
324    //      public static boolean copy( final String fromFile,final String toFile,final boolean changeCrLf ) {
325            public static boolean copy( final String fromFile,final String toFile,final boolean keepTimeStamp ) {
326                    return copy( new File( fromFile ), new File( toFile ), keepTimeStamp );
327            }
328    
329            /**
330             * ファイルのバイナリコピã?を行いますã?
331             *
332             * copy( File,File,false ) を呼び出しますã?
333             *
334             * @og.rev 5.1.6.0 (2010/05/01) 戻りå?に、true/false æŒ?®šしますã?
335             *
336             * @param       fromFile        コピã?å…?ƒ•ァイル
337             * @param       toFile          コピã?先ファイル
338             *
339             * @return      バイナリコピã?が正常に終äº?�—たかどã�?�‹[true:成功/false:失敗]
340             * @see         #copy( File,File,boolean )
341             */
342            public static boolean copy( final File fromFile,final File toFile ) {
343                    return copy( fromFile, toFile, false );
344            }
345    
346            /**
347             * ファイルのバイナリコピã?を行いますã?
348             *
349             * 第?“引数の、keepTimeStamp=true で、コピã?å…??ファイルのタイãƒ?‚¹タンプをã€?
350             * コピã?先にもセãƒ?ƒˆしますã?
351             * toFile がã?ãƒ?‚£レクトリの場合ã?、fromFile のファイル名をそã?ままコピã?しますã?
352             * fromFile がディレクトリの場合ã?、エラーにしますã?
353             * copyDirectry( File,Fileboolean )を使用してくださいã€?自動å?ç�??してã�?�¾せん)
354             *
355             * @og.rev 5.1.6.0 (2010/05/01) 新規追åŠ?
356             * @og.rev 5.6.5.2 (2013/06/21) ByteBufferを利用した方式からã?transferTo を使用する方式に変更
357             *
358             * @param       fromFile        コピã?å…?ƒ•ァイル
359             * @param       toFile          コピã?先ファイル
360             * @param       keepTimeStamp タイãƒ?‚¹タンプ維持[true/false]
361             *
362             * @return      バイナリコピã?が正常に終äº?�—たかどã�?�‹[true:成功/false:失敗]
363             * @see         #copyDirectry( File,File,boolean )
364             */
365            public static boolean copy( final File fromFile,final File toFile,final boolean keepTimeStamp ) {
366                    FileInputStream  inFile  = null;
367                    FileOutputStream outFile = null;
368                    FileChannel  fin  = null;
369                    FileChannel  fout = null;
370    
371                    File tempToFile = toFile ;
372                    try {
373                            // fromFileがã?ãƒ?‚£レクトリの場合ã?、エラー
374                            if( fromFile.isDirectory() ) {
375                                    System.err.println( fromFile + " がディレクトリのため、å?ç�?�§きませんã€? );
376                                    return false;
377                            }
378                            // toFileがã?ãƒ?‚£レクトリの場合ã?、そのパスでファイル名をfromFileから取り出すã?
379                            if( toFile.isDirectory() ) {
380                                    tempToFile = new File( toFile,fromFile.getName() );
381                            }
382                            inFile  = new FileInputStream( fromFile );
383                            outFile = new FileOutputStream( tempToFile );
384    
385                            fin  = inFile.getChannel();
386                            fout = outFile.getChannel();
387    
388                            // 5.6.5.2 (2013/06/21) ByteBufferを利用した方式からã?transferTo を使用する方式に変更
389    //                      ByteBuffer buffer = ByteBuffer.allocateDirect( BUFSIZE );
390    //                      while ( (fin.read(buffer) != -1) || buffer.position() > 0) {
391    //                              buffer.flip();
392    //                              fout.write( buffer );
393    //                              buffer.compact();
394    //                      }
395    
396                            fin.transferTo(0, fin.size(), fout );
397    
398                    }
399                    catch ( IOException ex ) {
400                            System.out.println(ex.getMessage());
401                            return false;
402                    }
403                    finally {
404                            Closer.ioClose( inFile  ) ;
405                            Closer.ioClose( outFile );
406                            Closer.ioClose( fin  ) ;
407                            Closer.ioClose( fout );
408                    }
409    
410                    if( keepTimeStamp ) {
411                            return tempToFile.setLastModified( fromFile.lastModified() );
412                    }
413    
414                    return true;
415            }
416    //      public static boolean copy( final File fromFile,final File toFile,final boolean keepTimeStamp ) {
417    //              BufferedInputStream     fromStream = null;
418    //              BufferedOutputStream    toStream   = null;
419    //              File tempToFile = toFile ;
420    //              try {
421    //                      // fromFileがã?ãƒ?‚£レクトリの場合ã?、エラー
422    //                      if( fromFile.isDirectory() ) {
423    //                              System.err.println( fromFile + " がディレクトリのため、å?ç�?�§きませんã€? );
424    //                              return false;
425    //                      }
426    //                      // toFileがã?ãƒ?‚£レクトリの場合ã?、そのパスでファイル名をfromFileから取り出すã?
427    //                      if( toFile.isDirectory() ) {
428    //                              tempToFile = new File( toFile,fromFile.getName() );
429    //                      }
430    //
431    //                      fromStream = new BufferedInputStream( new FileInputStream( fromFile ) );
432    //                      toStream   = new BufferedOutputStream( new FileOutputStream( tempToFile ) );
433    //
434    //                      boolean isOK = copy( fromStream,toStream );
435    //                      if( !isOK ) { return false; }
436    //
437    //              }
438    //              catch ( IOException ex ) {
439    //                      System.out.println(ex.getMessage());
440    //                      return false;
441    //              }
442    //              finally {
443    //                      Closer.ioClose( fromStream ) ;
444    //                      Closer.ioClose( toStream ) ;
445    //              }
446    //
447    //              if( keepTimeStamp ) {
448    //                      tempToFile.setLastModified( fromFile.lastModified() );
449    //              }
450    //
451    //              return true;
452    //      }
453    
454            private static final byte B_CR = (byte)0x0d ;   // '\r'
455            private static final byte B_LF = (byte)0x0a ;   // '\n'
456            private static final int  BUFSIZE = 8192 ;              // 5.1.6.0 (2010/05/01)
457    
458            /**
459             * ファイルのバイナリコピã?を行いますã?
460             *
461             * こã?ファイルコピã?は、バイナリファイルの 改行コードを
462             * CR+LF に統ä¸?�—ますã?またã?UTF-8 の BOM(0xef,0xbb,0xbf) があれã?ã€?
463             * 取り除きますã?
464             *
465             * @og.rev 5.1.6.0 (2010/05/01) 新規追åŠ?
466             *
467             * @param       fromFile        コピã?å…?ƒ•ァイル
468             * @param       toFile          コピã?先ファイル
469             *
470             * @return      バイナリコピã?が正常に終äº?�—たかどã�?�‹[true:成功/false:失敗]
471             */
472            public static boolean changeCrLfcopy( final File fromFile,final File toFile ) {
473                    BufferedInputStream     fromStream = null;
474                    BufferedOutputStream    toStream   = null;
475                    File tempToFile = toFile ;
476                    try {
477                            // ãƒ?‚£レクトリの場合ã?、そのパスでファイル名をfromFileから取り出すã?
478                            if( toFile.isDirectory() ) {
479                                    tempToFile = new File( toFile,fromFile.getName() );
480                            }
481                            fromStream = new BufferedInputStream( new FileInputStream( fromFile ) );
482                            toStream   = new BufferedOutputStream( new FileOutputStream( tempToFile ) );
483    
484    //                      int BUFSIZE = 8192 ;            // 5.1.6.0 (2010/05/01) static final定義
485                            byte[] buf = new byte[BUFSIZE];
486                            int len ;
487                            // 4.2.3.0 (2008/05/26) changeCrLf 属æ?対å¿?
488    
489                            boolean bomCheck = true;        // æœ??のä¸?›žã�?�‘ã€?¼¢?¯?­チェãƒ?‚¯を行うã€?
490                            byte    bt = (byte)0x00;        // バッファのæœ?¾Œとæœ??の比è¼?™‚に使用
491                            while( (len = fromStream.read(buf,0,BUFSIZE)) != -1 ) {
492                                    int st = 0;
493                                    if( bomCheck && len >= 3 &&
494                                            buf[0] == (byte)0xef &&
495                                            buf[1] == (byte)0xbb &&
496                                            buf[2] == (byte)0xbf  ) {
497                                                    st = 3;
498                                    }
499                                    else {
500                                            // バッファのæœ?¾Œが CR で、å?頭ã�?LF の場合ã?LF をパスしますã?
501                                            if( bt == B_CR && buf[0] == B_LF ) {
502                                                    st = 1 ;
503                                            }
504                                    }
505                                    bomCheck = false;
506    
507                                    for( int i=st;i<len;i++ ) {
508                                            bt = buf[i] ;
509                                            if( bt == B_CR || bt == B_LF ) {
510                                                    toStream.write( (int)B_CR );            // CR
511                                                    toStream.write( (int)B_LF );            // LF
512                                                    // CR+LF の場å�?
513                                                    if( bt == B_CR && i+1 < len && buf[i+1] == B_LF ) {
514                                                            i++;
515                                                            bt = buf[i] ;
516                                                    }
517                                            }
518                                            else {
519                                                    toStream.write( (int)bt );
520                                            }
521                                    }
522                            }
523                            // æœ?¾Œが改行コードでなければ、改行コードを追åŠ?�—ますã?
524                            // ãƒ?‚­ストコピã?との互換性のため
525                            if( bt != B_CR && bt != B_LF ) {
526                                    toStream.write( (int)B_CR );            // CR
527                                    toStream.write( (int)B_LF );            // LF
528                            }
529                    }
530                    catch ( IOException ex ) {
531                            System.out.println(ex.getMessage());
532                            return false;
533                    }
534                    finally {
535                            Closer.ioClose( fromStream ) ;
536                            Closer.ioClose( toStream ) ;
537                    }
538    
539                    return true;
540            }
541    
542            /**
543             * 入出力ストリーãƒ?–“でãƒ??タの転送を行いますã?
544             *
545             * ここでは、すでに作æ?されたストリーãƒ?�«基づきã?ãƒ??タの入出力を行いますã?
546             * よって、å?にフォルãƒ?½œæ?ã‚??存在チェãƒ?‚¯、ファイルの削除などのå¿?¦�な処ç�??
547             * 済まして置ã�?�¦くださいã€?
548             * またã?こã?メソãƒ?ƒ‰å†?�§、ストリーãƒ??クロース処ç�??行ってã�?�¾せんã€?
549             *
550             * @og.rev 5.1.6.0 (2010/05/01) 新規追åŠ?
551             *
552             * @param       input   入力ストリーãƒ?
553             * @param       output  出力ストリーãƒ?
554             *
555             * @return      ãƒ??タ転送が正常に終äº?�—たかどã�?�‹[true:成功/false:失敗]
556             */
557            public static boolean copy( final InputStream input,final OutputStream output ) {
558                    if( input == null ) {
559                            System.err.println( "入力ストリーãƒ?�Œ 作æ?されてã�?�¾せんã€? );
560                            return false;
561                    }
562    
563                    if( output == null ) {
564                            System.err.println( "出力ストリーãƒ?�Œ 作æ?されてã�?�¾せんã€? );
565                            return false;
566                    }
567    
568                    try {
569                            byte[] buf = new byte[BUFSIZE];
570                            int len;
571                            while((len = input.read(buf)) != -1) {
572                                    output.write(buf, 0, len);
573                            }
574                    }
575                    catch ( IOException ex ) {
576                            System.out.println( ex.getMessage() );
577                            return false;
578                    }
579            //      finally {
580            //              Closer.ioClose( input );
581            //              Closer.ioClose( output );
582            //      }
583                    return true ;
584            }
585    
586            /**
587             * 再帰処ç�?�§ãƒ?‚£レクトリのコピã?を行いますã?
588             *
589             * æŒ?®šされたコピã?å…?ƒ‡ィレクトリがディレクトリでなかったり存在しなã�?�¨きã?  falseを返しますã?
590             *
591             * @og.rev 4.3.0.0 (2008/07/24) 追åŠ?
592             * @og.rev 5.1.6.0 (2010/05/01) 戻りå?に、true/false æŒ?®šしますã?
593             *
594             * @param       fromDir コピã?å…?ƒ‡ィレクトリå�?
595             * @param       toDir   コピã?先ディレクトリå�?
596             *
597             * @return      ãƒ?‚£レクトリのコピã?が正常に終äº?�—たかどã�?�‹[true:成功/false:失敗]
598             */
599            public static boolean copyDirectry( final String fromDir, final String toDir ) {
600                    return copyDirectry( new File( fromDir ), new File( toDir ),false );
601            }
602    
603            /**
604             * 再帰処ç�?�§ãƒ?‚£レクトリをコピã?しますã?
605             *
606             * æŒ?®šされたコピã?å…?ƒ‡ィレクトリがディレクトリでなかったり存在しなã�?�¨きã?  falseを返しますã?
607             *
608             * @og.rev 4.3.0.0 (2008/07/24) 追åŠ?
609             * @og.rev 5.1.6.0 (2010/05/01) å†?ƒ¨処ç�?‚’若干変更しますã?
610             *
611             * @param       fromDir   コピã?å…?ƒ‡ィレクトリ
612             * @param       toDir     コピã?先ディレクトリ
613             *
614             * @return      ãƒ?‚£レクトリのコピã?が正常に終äº?�—たかどã�?�‹[true:成功/false:失敗]
615             */
616            public static boolean copyDirectry( final File fromDir, final File toDir ) {
617                    return copyDirectry( fromDir, toDir, false );
618            }
619    
620            /**
621             * 再帰処ç�?�§ãƒ?‚£レクトリをコピã?しますã?
622             *
623             * æŒ?®šされたコピã?å…?ƒ‡ィレクトリがディレクトリでなかったり存在しなã�?�¨きã?  falseを返しますã?
624             *
625             * @og.rev 4.3.0.0 (2008/07/24) 追åŠ?
626             * @og.rev 5.1.6.0 (2010/05/01) å†?ƒ¨処ç�?‚’若干変更しますã?
627             * @og.rev 5.3.7.0 (2011/07/01) フォルãƒ?�«アクセスできなã�??合ã?、エラーを返しますã?
628             *
629             * @param       fromDir コピã?å…?ƒ‡ィレクトリ
630             * @param       toDir   コピã?先ディレクトリ
631             * @param       keepTimeStamp タイãƒ?‚¹タンプ維持[true/false]
632             *
633             * @return      ãƒ?‚£レクトリのコピã?が正常に終äº?�—たかどã�?�‹[true:成功/false:失敗]
634             */
635            public static boolean copyDirectry( final File fromDir, final File toDir, final boolean keepTimeStamp ) {
636                    // コピã?å…?�Œãƒ?‚£レクトリでなã�??合ã?falseを返す
637                    // 4.3.4.4 (2009/01/01)
638                    if( !fromDir.exists() || !fromDir.isDirectory() ) {
639                            System.err.println( fromDir + " ã�?ãƒ?‚£レクトリでなã�?�‹、存在しませんã€? );
640                            return false;
641                    }
642    
643                    // 4.3.4.4 (2009/01/01)
644                    if( !toDir.exists() ) {
645                            // ãƒ?‚£レクトリを作æ?する
646                            if( !toDir.mkdirs() ) {
647                                    System.err.println( toDir + " の ãƒ?‚£レクトリ作æ?に失敗しましたã€? );
648                                    return false;
649                            }
650                    }
651    
652                    // ãƒ?‚£レクトリå†??ファイルをすべて取得すã‚?
653                    File[] files = fromDir.listFiles();
654    
655                    // 5.3.7.0 (2011/07/01) フォルãƒ?�«アクセスできなã�??合ã?、エラー
656                    if( files == null ) {
657                            System.err.println( fromDir + " はアクセスできませんã€? );
658                            return false;
659                    }
660    
661                    // ãƒ?‚£レクトリå†??ファイルに対しコピã?処ç�?‚’行う
662                    boolean flag = true;
663                    for( int i = 0; files.length>i; i++ ){
664                            if( files[i].isDirectory() ){ // ãƒ?‚£レクトリã�?�£たå?合ã?再帰呼び出しを行う
665                                    flag = copyDirectry( files[i], new File( toDir, files[i].getName()),keepTimeStamp );
666                            }
667                            else{ // ファイルã�?�£たå?合ã?ファイルコピã?処ç�?‚’行う
668                                    flag = copy( files[i], new File( toDir, files[i].getName()),keepTimeStamp );
669                            }
670                            if( !flag ) { return false; }
671                    }
672                    return true;
673            }
674    //      public static boolean copyDirectry( final File fromDirectry, final File toDirectry ) {
675    //              // コピã?å…?�Œãƒ?‚£レクトリでなã�??合ã?falseを返す
676    //              // 4.3.4.4 (2009/01/01)
677    //              if( !fromDirectry.exists() || !fromDirectry.isDirectory() ) { return false; }
678    //
679    //              // 4.3.4.4 (2009/01/01)
680    //              boolean flag = true;
681    //              if( !toDirectry.exists() ) {
682    //                      // ãƒ?‚£レクトリを作æ?する
683    //                      flag = toDirectry.mkdirs();
684    //                      if( ! flag ) { System.err.println( toDirectry.getName() + " の ãƒ?‚£レクトリ作æ?に失敗しましたã€? ); }
685    //              }
686    //
687    //              // ãƒ?‚£レクトリå†??ファイルをすべて取得すã‚?
688    //              File[] files = fromDirectry.listFiles();
689    //
690    //              // ãƒ?‚£レクトリå†??ファイルに対しコピã?処ç�?‚’行う
691    //              for( int i = 0; files.length>i; i++ ){
692    //                      if( files[i].isDirectory() ){ // ãƒ?‚£レクトリã�?�£たå?合ã?再帰呼び出しを行う
693    //                              copyDirectry(
694    //                              new File( fromDirectry.toString(), files[i].getName() ),
695    //                              new File( toDirectry.toString(), files[i].getName()));
696    //                      }
697    //                      else{ // ファイルã�?�£たå?合ã?ファイルコピã?処ç�?‚’行う
698    //                              copy(
699    //                              new File( fromDirectry.toString(), files[i].getName() ),
700    //                              new File( toDirectry.toString(), files[i].getName()) );
701    //                      }
702    //              }
703    //              return true;
704    //      }
705    
706            /**
707             * æŒ?®šされたファイル及ã?ãƒ?‚£レクトを削除しますã?
708             * ãƒ?‚£レクトリの場合ã?サブフォルãƒ?�Šびファイルも削除しますã?
709             * ?‘つでもファイルの削除に失敗したå?合ã?そã?時点で処ç�?‚’中断しfalseを返しますã?
710             *
711             * @og.rev 5.3.7.0 (2011/07/01) フォルãƒ?�«アクセスできなã�??合ã?、エラーを返しますã?
712             *
713             * @param       file 削除ファイル/ãƒ?‚£レクトリ
714             *
715             * @return      ファイル/ãƒ?‚£レクトリの削除に終äº?�—たかどã�?�‹[true:成功/false:失敗]
716             */
717            public static boolean deleteFiles( final File file ) {
718                    if( file.exists() ) {
719                            if( file.isDirectory() ) {
720                                    File[] list = file.listFiles();
721    
722                                    // 5.3.7.0 (2011/07/01) フォルãƒ?�«アクセスできなã�??合ã?、エラー
723                                    if( list == null ) {
724                                            System.err.println( file + " はアクセスできませんã€? );
725                                            return false;
726                                    }
727    
728                                    for( int i=0; i<list.length; i++ ) {
729                                            deleteFiles( list[i] );
730                                    }
731                            }
732                            if( !file.delete() ) { return false; }
733                    }
734                    return true;
735            }
736    
737            /**
738             * æŒ?®šされたãƒ?‚£レクトリを基点としたファイルå�?パスを含ã‚?のä¸?¦§を返しますã?
739             *
740             * @og.rev 4.3.6.6 (2009/05/15) 新規作æ?
741             * @og.rev 5.4.3.2 (2012/01/06) 引数isCopy追åŠ?
742             *
743             * @param dir 基点となるディレクトリ
744             * @param sort ファイル名でソートするか
745             * @param list ファイル名ä¸?¦§をæ?納するList
746             * @param isCopy コピã?中ファイルを除外するか [true:含ã‚?false:除外]
747             */
748            public static void getFileList( final File dir, final boolean sort, final List<String> list, boolean isCopy ) {
749                    if( list == null ) { return; }
750                    if( dir.isFile() ) {
751                            // コピã?中判定ã?renameで行う
752                            if( !isCopy && !dir.renameTo( dir ) ){
753                                    return;
754                            }
755                            else{
756                                    list.add( dir.getAbsolutePath() );
757                            }
758                    }
759                    else if( dir.isDirectory() ) {
760                            File[] files = dir.listFiles();
761                            for( int i=0; i<files.length; i++ ) {
762                                    getFileList( files[i], sort, list, isCopy );
763                            }
764                    }
765                    if( sort ) {
766                            Collections.sort( list );
767                    }
768            }
769    
770            /**
771             * æŒ?®šされたãƒ?‚£レクトリを基点としたファイルå�?パスを含ã‚?のä¸?¦§を返しますã?
772             * 互換性のため、コピã?中ファイルも含みますã?
773             *
774             * @og.rev 5.4.3.2 (2012/01/06) コピã?中対応ã?ため引数?”つを作æ?する
775             *
776             * @param dir 基点となるディレクトリ
777             * @param sort ファイル名でソートするか
778             * @param list ファイル名ä¸?¦§をæ?納するList
779             */
780            public static void getFileList( final File dir, final boolean sort, final List<String> list ) {
781                            getFileList( dir, sort, list, true );
782            }
783    
784            /**
785             * æŒ?®šされたファイルå�?パスを含ã‚?から、パスも拡張子もなã�?ƒ•ァイル名を返しますã?
786             *
787             * @og.rev 5.6.1.2 (2013/02/22) 新規作æ?
788             *
789             * @param filename ファイルå�?パスを含ã‚?
790             * @return パスもã?拡張子もなã�?ƒ•ァイルå�?
791             */
792            public static String getBaseName( final String filename ) {
793    
794                    if (filename == null) {
795                            return null;
796                    }
797    
798                    // セパレータの位置を取得ã?
799                    int lastUnixPos    = filename.lastIndexOf(UNIX_SEPARATOR);
800                    int lastWindowsPos = filename.lastIndexOf(WINDOWS_SEPARATOR);
801                    int lastSepPos = Math.max( lastUnixPos , lastWindowsPos );
802    
803                    // 拡張子ã?位置を取得ã?
804                    int extPos = filename.lastIndexOf(EXTENSION_SEPARATOR);
805                    if( lastSepPos > extPos ) { extPos = -1; }   // 念のため、最後ã?セパレータより前にある拡張子ã?区åˆ?‚Šæ–?­—ã?無効ã€?
806    
807                    if( extPos < 0 ) {
808                            // SEPARATOR がなければ、lastSepPos + 1 = 0 となりã?先é?から取得できるã€?
809                            return filename.substring( lastSepPos + 1 );
810                    } else {
811                            return filename.substring( lastSepPos + 1 , extPos );
812                    }
813            }
814    
815            /**
816             * PrintWriter を継承した、System.out/System.err 用のクラスを定義しますã?
817             *
818             * 通常の、new PrintWriter( OutputStream ) で、求めるã?と、ほとんど同様ã?
819             * 処ç�?‚’行いますã?
820             * ただ、close() メソãƒ?ƒ‰が呼ばれてもã?何もしませんã€?
821             *
822             */
823            private static final class NonClosePrintWriter extends PrintWriter {
824                    /**
825                     * コンストラクター
826                     *
827                     * new PrintWriter( OutputStream ) を行いますã?
828                     *
829                     * @param out OutputStream
830                     */
831                    public NonClosePrintWriter( final OutputStream out ) {
832                            super( out );
833                    }
834    
835                    /**
836                     * close() メソãƒ?ƒ‰をオーバã?ライドしますã?
837                     *
838                     * 何もしませんã€?
839                     *
840                     */
841                    public void close() {
842                            // ここでは処ç�?‚’行いませんã€?
843                    }
844            }
845    
846            /**
847             * PrintWriter を継承した、JspWriterなどの Writer 用のクラスを定義しますã?
848             *
849             * 例えば、JspWriterなどの JSP/Servlet等ã?フレーãƒ?ƒ¯ークで使用されã‚?
850             * Writer では、flush ã‚?close 処ç�??、フレーãƒ?ƒ¯ークå†?�§行われますã?
851             * そã?場合ã?通常のファイルと同じ用に、flush ã‚?close をアプリケーション側で
852             * 行うと、å?部処ç�?š„に不整合が発生したり、最悪の場合エラーになりますã?
853             * こã?クラスは、単にã€??常の、new PrintWriter( Writer ) で、求めるã?とã€?
854             * ほとんど同様ã?処ç�?‚’行いますã?
855             * ただ、close() と flush() メソãƒ?ƒ‰が呼ばれてもã?何もしませんã€?
856             *
857             */
858            private static final class NonFlushPrintWriter extends PrintWriter {
859                    /**
860                     * コンストラクター
861                     *
862                     * new PrintWriter( Writer ) を行いますã?
863                     *
864                     * @param writer Writer
865                     */
866                    public NonFlushPrintWriter( final Writer writer ) {
867                            super( writer );
868                    }
869    
870                    /**
871                     * close() メソãƒ?ƒ‰をオーバã?ライドしますã?
872                     *
873                     * 何もしませんã€?
874                     *
875                     */
876                    public void close() {
877                            // ここでは処ç�?‚’行いませんã€?
878                    }
879    
880                    /**
881                     * flush() メソãƒ?ƒ‰をオーバã?ライドしますã?
882                     *
883                     * 何もしませんã€?
884                     *
885                     */
886                    public void flush() {
887                            // ここでは処ç�?‚’行いませんã€?
888                    }
889            }
890    
891            /**
892             * ファイルをコピã?しますã?
893             *
894             * 引数に <file1> <file2> [<encode1> <encode2>] を指定しますã?
895             * file1 を読み込み、file2 にコピã?しますã?コピã?前に、file2 は、file2_backup にコピã?しますã?
896             * file1 がã?ãƒ?‚£レクトリの場合ã?、ディレクトリごとコピã?しますã?
897             * encode1、encode2 を指定すると、エンコード変換しながらコピã?になりますã?
898             * こã?場合ã?、ファイル同士のコピã?のみになりますã?
899             *
900             * @og.rev 4.0.0.0 (2007/11/28) メソãƒ?ƒ‰の戻りå?をチェãƒ?‚¯しますã?
901             * @og.rev 5.1.6.0 (2010/05/01) 引数の並びé ??処ç�?‚’変更しますã?
902             *
903             * @param       args 引数配å?  file1 file2 [encode1 encode2]
904             */
905            public static void main( final String[] args ) throws Throwable {
906                    if( args.length != 2 && args.length != 4 ) {
907                            LogWriter.log("Usage: java FileUtil <file1> <file2> [<encode1> <encode2>]" );
908                            return ;
909                    }
910    
911                    File file1 = new File( args[0] );
912                    File file2 = new File( args[1] );
913    
914                    File tempFile = new File( args[1] + "_backup" );
915    
916                    if( args.length < 3 ) {
917                            if( file1.isDirectory() ) {
918                                    FileUtil.copyDirectry( file1, file2, true );
919                            }
920                            else {
921                                    FileUtil.copy( file2,tempFile );
922                                    FileUtil.copy( file1,file2, true );
923                            }
924                    }
925                    else {
926                            String encode1 = args[2];
927                            String encode2 = args[3];
928    
929                            FileUtil.copy( file2,tempFile );
930    
931                            BufferedReader reader = FileUtil.getBufferedReader( file1 ,encode1 );
932                            PrintWriter    writer = FileUtil.getPrintWriter(    file2 ,encode2 );
933    
934                            try {
935                                    String line1;
936                                    while((line1 = reader.readLine()) != null) {
937                                            writer.println( line1 );
938                                    }
939                            }
940                            finally {
941                                    Closer.ioClose( reader ) ;
942                                    Closer.ioClose( writer ) ;
943                            }
944                    }
945            }
946    }