ファイル・ディレクトリに対する操作

 今までのサンプルでもFilesクラスの様々な機能を使用してきましたが、Filesクラスにはまだ多くの機能があります。その中には、ファイルやディレクトリに対する操作があります。

 ファイル・ディレクトリに対する操作というのは、ファイル・ディレクトリのコピー、移動、削除などのことです。

 特にコピーは今まで提供されておらず、ストリームやチャネルなどを使用して記述するしかありませんでした。コピーは使用頻度も高いので、Filesクラスで実現できるのはうれしいところです。

サンプルのソース (こちらからダウンロードできます)
・OperationDemo.java

コピー

 ファイル・ディレクトリのコピーはFilesクラスのcopyメソッドで行います。

リスト6●ファイルのコピー
            Path foo = fileSystem.getPath("foo.txt");
            Path bar = fileSystem.getPath("bar.txt");
            Path baz = fileSystem.getPath("baz.txt");
 
            // ファイルのコピー
            Files.copy(foo, bar);
 
            // ファイルのコピー(上書きコピー)
            Files.copy(foo, bar, 
                       StandardCopyOption.REPLACE_EXISTING);
                        
            // ファイルのコピー(属性を含む)
            Files.copy(foo, baz,
                       StandardCopyOption.COPY_ATTRIBUTES);

 単純にコピーを行うのであれば、copyメソッドの第1引数にコピー元ファイル、第2引数にコピー先ファイルを指定します。

 コピー元ファイルが存在しない場合、NoSuchFileException例外がスローされます。また、既にコピー先ファイルが存在する場合、FileAlreadyExistsException例外がスローされます。

 もし、コピー先ファイルが存在していても上書きしていいのであれば、copyメソッドの第3引数にjava.nio.file.StandardCopyOption.REPLACE_EXISTINGを指定します。

 StandardCopyOptionはenumであり、次の定数が定義されています。

  • REPLACE_EXISTING 上書きする
  • COPY_ATTRIBUTES アトリビュートもコピー
  • ATOMIC_MOVE アトミック処理

 COPY_ATTRIBUTESを使用したのが、上記のコードの青字の部分です。この場合、最終アクセス時刻などが一緒にコピーされます。

 最後のATOMIC_MOVEはコピーでは使用できず、移動で使用します。

 また、StandardCopyOption以外に、前回使用したLinkOptionも使用できます。

 copyメソッドの第3引数からは可変長引数になっているので、これらの定数を複数同時に指定することも可能です。

 ファイル名を同じにしたまま、他のディレクトリにコピーすることも多くあります。このような場合、Windowsのcopyコマンド、Linux/Solarisのcpコマンドでは第2オプションにディレクトリを指定することができます。

 例えば、以下のような例です。

C:\nio2>dir
 ドライブ C のボリューム ラベルがありません。
 ボリューム シリアル番号は 6E12-98A9 です

 C:\nio2のディレクトリ

2011/08/18  22:18    <DIR>          .
2011/08/18  22:18    <DIR>          ..
2011/08/20  23:42    <DIR>          dir1
2011/08/21  23:18                 8 foo.txt
               1 個のファイル                   8 バイト
               2 個のディレクトリ  165,088,886,784 バイトの空き領域 
C:\nio2>copy foo.txt dir1
        1 個のファイルをコピーしました。
 
C:\nio2>

 しかし、copyメソッドでは必ず対応するファイルを必ず指定しなくてはなりません。

リスト7●ファイルを他のディレクトリにコピー
            // 他のディレクトリにファイルをコピー
            Path foo = fileSystem.getPath("foo.txt");
            Path foo2 = fileSystem.getPath("dir1", "foo.txt");
            
            Files.copy(foo, foo2);

 ディレクトリのコピーも同じように行うことができます。

 foo.txtファイルが配置されているdir1ディレクトリを、dir2ディレクトリにコピーしてみましょう。

リスト8●ディレクトリのコピー
            // ディレクトリのコピー
            Path dir1 = fileSystem.getPath("dir1");
            Path dir2 = fileSystem.getPath("dir2");
 
            Files.copy(dir1, dir2);

 では、実行してみましょう。

C:\nio2>java OperationDemo
 
C:\nio2>dir dir2
 ドライブ C のボリューム ラベルがありません。
 ボリューム シリアル番号は 6E12-98A9 です

 C:\dir2のディレクトリ

2011/08/21  23:42    <DIR>          .
2011/08/18  22:18    <DIR>          ..
                0 個のファイル                   0 バイト
               2 個のディレクトリ  165,088,886,784 バイトの空き領域

 dir2ディレクトリは作成されたものの、dir1ディレクトリにあったfoo.txtファイルはコピーされていないようです。もし、ファイルツリーを辿って、すべてのファイル、ディレクトリをコピーするのであれば、後述するjava.nio.file.FileVisitorインタフェースを使用する必要があります。

 特殊な場合として、コピー元やコピー先にストリームを指定することができます。

リスト9●コピー元とコピー先にストリームを指定したコピー
            // ストリームからファイルにコピー
            InputStream in = Files.newInputStream(foo);
            Files.copy(in, bar,
                       StandardCopyOption.REPLACE_EXISTING);
            in.close();
            
            // ファイルからストリームにコピー
            OutputStream out = Files.newOutputStream(baz);
            Files.copy(foo, out);
            out.close();

 ストリームからファイルにコピーを行う場合はCopyOptionを指定できます。

この先は会員の登録が必要です。今なら有料会員(月額プラン)は12月末まで無料!

日経 xTECHには有料記事(有料会員向けまたは定期購読者向け)、無料記事(登録会員向け)、フリー記事(誰でも閲覧可能)があります。有料記事でも、登録会員向け配信期間は登録会員への登録が必要な場合があります。有料会員と登録会員に関するFAQはこちら