LoginSignup
4
2

More than 5 years have passed since last update.

Javaにおけるファイルコピー処理について

Last updated at Posted at 2017-02-03

結論

  • Java7以降で、特別な事情がない場合は java.nio.file.Files#copy(Path, Path, CopyOption) 等、標準ライブラリの機能をご利用ください。

  • Java6以前の場合、可能であれば Apache Commons の、Commons-IOに含まれるFileUtils#copyFile(File, File) 等、定評のあるライブラリの機能をご利用ください。

どうしても独自実装したい場合

2017年現在、独自実装する必要はないはずですが、なんらかの理由により独自実装する場合の話です。Webを検索すると、以下のようなコードが散見されます。

サンプル1

public static void copyFile(File sf, File df) {
        FileChannel sc = null, dc = null;
        try {
            sc = new FileInputStream(sf).getChannel();
            dc = new FileOutputStream(df).getChannel();
            dc.transferFrom(sc, 0, sc.size());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (dc != null) try { dc.close(); } catch (IOException e) {}
            if (sc != null) try { sc.close(); } catch (IOException e) {}
        }
    }

このメソッド、基本的には動作に問題ないのですが、静的構文解析ツールによっては、

    sc = new FileInputStream(sf).getChannel();

このFileChannelをメソッドチェインで取得している箇所で、「FileInputStreamが閉じられていない可能性がある」と警告してきます (FileOutputStreamも同様)

幸い、Java6の java.io.FileInputStream#close() のドキュメントには、

ファイル入力ストリームを閉じ、このストリームに関連するシステムリソースを解放します。
このストリームにチャネルが関連付けられている場合は、そのチャネルも閉じます。

とありますので、FileInputStream(FileOutputStream)を閉じましょう。こんな感じでしょうか (FileChannelも閉じても問題ないです。FileInputStreamとFileChannel、両方のcloseメソッドを呼んでも落ちることはありません。意味もありませんが)

サンプル2
    public static void copyFile(File sf, File df) {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream(sf);
            fos = new FileOutputStream(df);

            FileChannel sc = fis.getChannel();
            FileChannel dc = fos.getChannel();
            dc.transferFrom(sc, 0, sc.size());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) try { fos.close(); } catch (IOException e) {}
            if (fis != null) try { fis.close(); } catch (IOException e) {}
        }
    }

ということで、サンプル2の方が、後から静的構文解析ツール等を導入した際、警告される可能性が低くなります。Webを検索してサンプル1をコピペするくらいなら、サンプル2をご利用ください。後でメンテナンスする人が楽になりますので

なお、Java7以降で独自実装する場合は、try-with-resources文をお使いください。すごくシンプルになります。

参考

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2