こんにちは!フリーランスエンジニアのオータケです。
Java言語でファイルの作成やコピーなどを行う際にはjava.io.Fileクラスなどを使ってファイル処理を行っていました。
しかし、このjava.io.Fileクラスには様々な問題があるためJDK7からはjava.nio.file.Filesというクラスで処理を書いていくべきでしょう。この記事では、
java.nioとは
- ファイルの操作方法(ファイル移動、リネーム、copyメソッド、削除)
- ディレクトリの操作方法(ディレクトリ生成、ディレクトリかどうかを取得)
という基本的な内容から、
- 別のディレクトリにコピーする方法
- 上書き保存をする方法
などの応用的な使い方に関しても解説していきます。
今回はこれらの方法を覚えるために、java.nio.file.Filesクラスの基本的な使い方をわかりやすく解説します!
なお、Javaの記事については、こちらにまとめています。
java.nioとは?
本記事ではJDK7から追加されたjava.nioについて解説をしていきます。Javaには旧来からファイルやディレクトリの処理を行うAPIがありましたが、幾つか問題点もありJDK7からは新しくNewI/O 2というファイル処理のAPIが用意されました。
(java.nioには2つあり、JDK7から追加されたものはNewI/O 2と呼ばれており、旧来からあるjava.nioはこの記事では解説しておりません。)
APIとはなんだろう?という方には次の記事を読んでからこの記事を読んでいただくことをおすすめします!
特に本記事ではjava.nio.file.Filesクラスの使い方を解説します。
Java6以前ではjava.io.Fileクラスやjava.nio.FileChannelクラスなどがありましたがJava7からはjava.nio.file.Filesを使うことでとても簡単にファイル処理を行うことができます。
また、次の点でjava.io.Fileクラスには欠点があるため特段理由がなければjava.nio.file.Filesクラスを使うのが良いかと思います。(オラクル公式ドキュメントから引用)
- 多くのメソッドで、失敗時に例外がスローされないため、有用なエラー・メッセージを取得できない。
たとえば、ファイルの削除が失敗した場合に、プログラムでは”削除が失敗したこと”は認識できるが、その理由としてファイルが存在しないのか、ユーザーに権限がないのか、または他の問題があるのかが分からない。
- renameメソッドの動作が、プラットフォーム間で一貫していない。
- シンボリック・リンクが十分にサポートされていない。
- ファイル権限、ファイル所有者、その他のセキュリティ属性などのメタデータに対して、より広範なサポートが求められる。
- ファイル・メタデータへのアクセスが非効率的である。
- Fileの多くのメソッドにスケーラビリティがない。 大きなディレクトリのリスト作成をサーバーにリクエストすると、ハングすることがある。 大きなディレクトリによってメモリ・リソースの問題が発生し、結果としてサービスが拒否されることがある。
- ファイル・ツリーを再帰的に探索し、循環シンボリック・リンクがある場合は適切に対応する、信頼性の高いコードを記述できない。
これを見てもよくわからない方は、とりあえず理由がない限りはjava.nioを用いたファイル処理を書けば良いんだな、と理解しておきましょう。
なお、Java6以前でのjava.io.Fileクラスを用いたファイルのコピー方法を知りたい方は次の記事をご覧ください!
旧来のファイル処理について知りたい方は上記記事でわかりやすく解説しています。では本記事の目的であるjava.nioを使って次の章からファイル操作を学んでみましょう!
ファイルの操作
Filesクラスを使ってファイルを移動する
import java.io.IOException; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; public class Main { public static void main(String[] args) throws Exception { String spa = FileSystems.getDefault().getSeparator(); try { Path sourcePath = Paths.get("." + spa + "Test.txt"); Path targetPath = Paths.get("." + spa + "Sample" + spa + "Test.txt"); Files.move(sourcePath, targetPath); System.out.println("移動が成功しました"); } catch (IOException e) { e.printStackTrace(); } } }
Filesクラスのmoveメソッドを使うことでファイルを移動することができます。移動方法についてですが、moveメソッドの第一引数には移動元となるファイルが置いてあるパスを指定します。
第二引数には移動先となるファイルが置いてあるパスを指定します。こうすることでファイルの移動をすることができました。
ファイルをリネームする方法
ファイルのリネームをするには、moveメソッドの第二引数で変更後のファイル名を指定します。
次のプログラムで確認してみましょう。
import java.io.IOException; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; public class Main { public static void main(String[] args) throws Exception { String spa = FileSystems.getDefault().getSeparator(); try { Path sourcePath = Paths.get("." + spa + "Test.txt"); Path targetPath = Paths.get("." + spa + "Sample" + spa + "Test2.txt"); Files.move(sourcePath, targetPath); System.out.println("移動が成功しました"); } catch (IOException e) { e.printStackTrace(); } } }
移動先のパスに別の元のファイル名とは違うファイル名を指定した場合はファイルをリネームすることになります。
Filesクラスのcopyメソッドの使い方
ここではcopyメソッドを使ってファイルをコピーする方法を解説します。ファイルのコピーはcopyメソッドの引数に、コピー元のファイルのパスと、コピー先のパスを指定するだけです。
copyメソッドの使い方を次のプログラムで確認してみましょう!
import java.io.IOException; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; public class Main { public static void main(String[] args) throws Exception { String spa = FileSystems.getDefault().getSeparator(); try { Path sourcePath = Paths.get("." + spa + "Test.txt"); Path targetPath = Paths.get("." + spa + "Sample" + spa + "Test.txt"); Files.copy(sourcePath, targetPath); System.out.println("コピーが成功しました"); } catch (IOException e) { e.printStackTrace(); } } }
[実行結果]
コピーが成功しました
このプログラムでは、指定したファイルを別のディレクトリにコピーしています。
copyメソッドを使ってファイルのコピーができることが確認できました!
上書き保存をする方法
ここではファイルのコピー先にすでに同名のファイルが存在する場合に、上書き保存をする方法を解説します。ファイルを上書き保存するには、copyメソッドの引数にオプションのStandardCopyOption.REPLACE_EXISTINGを追加します。
オプションを設定しない状態でコピー先にファイルが存在する場合には、FileAlreadyExistsExceptionの例外が発生するので注意してください。
ファイルを上書き保存する方法を覚えるために、次のプログラムで確認してみましょう!
import java.io.IOException; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; public class Main { public static void main(String[] args) throws Exception { String spa = FileSystems.getDefault().getSeparator(); try { Path sourcePath = Paths.get("." + spa + "Test.txt"); Path targetPath = Paths.get("." + spa + "Sample" + spa + "Test.txt"); Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING); System.out.println("コピーが成功しました"); } catch (IOException e) { e.printStackTrace(); } } }
[実行結果]
コピーが成功しました
StandardCopyOption.REPLACE_EXISTINGオプションを指定して、上書き保存ができることが確認できました!
ファイルを削除する方法
最後にファイルを削除する方法について見てみましょう。ではサンプルコードをご覧ください。
import java.io.IOException; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; public class Main { public static void main(String[] args) throws Exception { try { String spa = FileSystems.getDefault().getSeparator(); Path targetPath = Paths.get("." + spa + "Sample" + spa + "Test.txt"); if(Files.deleteIfExists(targetPath)) { System.out.println("削除できました!"); } else { System.out.println("ファイルが無いようです!"); } } catch (IOException e) { e.printStackTrace(); } } }
今回はdeleteIfExistsメソッドを使ってファイルを削除しています。引数には削除対象となるファイルへのパスを指定しています。このメソッドは削除に成功するとtrueを返し、失敗するとfalseを返します。
ファイル削除のメソッドは扱う際には重要なファイルや消してはいけないファイルを消さないように十分注意しましょう!
ディレクトリの操作
createDirectoriesを使ってディレクトリ作成
では続いてディレクトリの操作について見てみましょう。最初はディレクトリを作成する方法について解説します。
早速サンプルコードを見てみましょう!
import java.io.IOException; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; public class Main { public static void main(String[] args) throws Exception { String spa = FileSystems.getDefault().getSeparator(); try { Path targetPath = Paths.get("." + spa + "SampleDirectory"); Files.createDirectories(targetPath); System.out.println("ディレクトリを作成しました。"); } catch (IOException e) { e.printStackTrace(); } } }
サンプルコードではcreateDirectoriesメソッドを使ってディレクトリを作成しています。引数には作成するディレクトリについての情報を渡しています。
今回の場合では現在の場所にSampleDirectoryというディレクトリ(フォルダ)を作成しています。サンプルコードを見てもピンとこない場合は実行して試してみましょう!
次にパスがディレクトリかどうかの判定を行う方法について解説します。
ディレクトリ(フォルダ)かどうかの判定
この項目では指定したパスがディレクトリなのか、ファイルなのかを知る方法について解説をします。
早速サンプルコードを見ながら実行してみましょう。
import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; public class Main { public static void main(String[] args) throws Exception { String spa = FileSystems.getDefault().getSeparator(); Path targetPath = Paths.get("." + spa + "SampleDirectory"); if(Files.isDirectory(targetPath)) { System.out.println("ディレクトリですよ!"); } else { System.out.println("ディレクトリじゃないですよ!"); } } }
今回のサンプルコードではisDirectoryメソッドを使っています。引数は他のファイル・ディレクトリ処理同様でパスを指定します。
このメソッドでは指定したパスがディレクトリである場合はtrueを返し、指定したパスがディレクトリではない場合はfalseを返します。
そのため今回のコードではif文でディレクトリかどうかによって表示する文字を切り替えています。こちらのメソッドも使い方として難しくないですよね?
ファイルの使い方総まとめ
ファイル操作の様々な方法は次の記事で詳しく解説しているので、ぜひ確認してください。
まとめ
いかがでしたか?今回はjava.nio.file.Filesクラスの使い方について解説しました。
特にcopyメソッドについてはオプションの指定を間違えると上書き保存ができないので注意してくださいね。
もしファイル処理の方法をを忘れてしまったらこの記事を確認してください!