/* * Copyright (c) 2011 NTT DATA Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jp.terasoluna.fw.batch.util; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.channels.Channel; import java.nio.channels.FileChannel; import jp.terasoluna.fw.file.dao.FileException; import jp.terasoluna.fw.file.util.FileUtility; /** * ファイルコピーを高速に行うユーティリティ。<br> * <br> * TERASOLUNAバッチフレームワークのFileUtilityによるコピーを行うと、ファイルロック、チャンク1024バイトによるバイト移送時により、特にNFSへのファイルコピーにて性能劣化が発生する。<br> * このため、NFSを使用したファイルコピーで性能が出ない場合は 当クラスによるファイルコピーを行うこと。 */ public class FastFileUtility extends FileUtility { /** * ファイルをコピーする。 * <p> * コピー元のファイルのパスを受け取り、 コピー先のパスにファイルをコピーする。<br> * コピー先にファイルが存在する場合、上書きでコピーされる。<br> * </p> * @param srcFile コピー元のファイルのパス * @param newFile コピー先のファイルのパス */ public static void copyFile(String srcFile, String newFile) { if (srcFile == null) { throw new FileException("srcFile is null."); } if (newFile == null) { throw new FileException("newFile is null."); } File srcFileObject = new File(srcFile); // コピー元のパスにファイルが存在しない場合、エラーを投げて処理を終了する。 if (!srcFileObject.exists()) { throw new FileException(srcFile + " is not exist."); } File outputFileObject = new File(newFile); copyFile(srcFileObject, outputFileObject); } /** * ファイルをコピーする。 * <p> * コピー元のファイルのパスを受け取り、 コピー先のパスにファイルをコピーする。<br> * コピー先にファイルが存在する場合、上書きでコピーされる。<br> * </p> * @param srcFile コピー元のファイルオブジェクト * @param newFile コピー先のファイルオブジェクト */ static void copyFile(File srcFile, File newFile) { FileInputStream fis = null; FileOutputStream fos = null; FileChannel ic = null; FileChannel oc = null; try { fis = new FileInputStream(srcFile); fos = new FileOutputStream(newFile); ic = fis.getChannel(); oc = fos.getChannel(); transferFileEntirely(ic, oc); } catch (IOException e) { throw new FileException("File control operation was failed.", e); } finally { closeQuietly(oc); closeQuietly(ic); closeQuietly(fos); closeQuietly(fis); } } /** * ファイルを完全にコピーする。 * @param srcChannel コピー元FileChannel * @param destChannel コピー先FileChannel */ private static void transferFileEntirely(FileChannel srcChannel, FileChannel destChannel) throws IOException { long srcFileSize = srcChannel.size(); long transferedSize = 0L; while(transferedSize < srcFileSize){ long transferSize = srcChannel.transferTo(transferedSize, srcFileSize - transferedSize, destChannel); transferedSize += transferSize; } } /** * Channelをクローズする。<br> * <p> * 引数に渡されたchannelがnullでなければクローズする。<br> * また、クローズする際にIOException例外が発生した場合は無視する。<br> * </p> * @param channel Channel */ public static void closeQuietly(Channel channel) { try { if (channel != null) { channel.close(); } } catch (IOException e) { // なにもしない } } /** * FileInputStreamをクローズする。<br> * <p> * 引数に渡されたstreamがnullでなければクローズする。<br> * また、クローズする際にIOException例外が発生した場合は無視する。<br> * </p> * @param stream FileInputStream */ public static void closeQuietly(FileInputStream stream) { try { if (stream != null) { stream.close(); } } catch (IOException e) { // なにもしない } } /** * FileOutputStreamをクローズする。<br> * <p> * 引数に渡されたstreamがnullでなければクローズする。<br> * また、クローズする際にIOException例外が発生した場合は無視する。<br> * </p> * @param stream FileOutputStream */ public static void closeQuietly(FileOutputStream stream) { try { if (stream != null) { stream.close(); } } catch (IOException e) { // なにもしない } } }