S-JIS[2011-07-30/2019-03-31] 変更履歴
Javaのファイル操作クラスは、JDK1.7(Java7)で新しいものが導入された。(通称NIO2(New I/O 2)。自分はニオツーって呼んでる)
→旧ファイル操作
Filesクラスでファイルのコピーや移動などを行うことが出来る。
また、ファイルやディレクトリーの場所を表すPathというインターフェースが新たに設けられた。
|
|
java.nio.file.Pathは、ファイルやディレクトリーの場所を表すインターフェース。
従来はjava.io.Fileクラスがその役割だった。
import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Path;
FileSystem fs = FileSystems.getDefault(); Path path1 = fs.getPath("C:/temp/zzz.txt"); Path path2 = fs.getPath("C:/temp/", "zzz.txt"); Path path3 = fs.getPath("C:", "temp", "zzz.txt");
(→FileSystemsを使ってzipファイルを読み書きする方法)
Pathsを使うことも出来る。[2014-03-21]
import java.nio.file.Path; import java.nio.file.Paths;
Path path = Paths.get("C:", "temp", "zzz.txt");
Path.ofを使うことも出来る。(Java11以降)[2014-03-21]
import java.nio.file.Path;
Path path = Path.of("C:", "temp", "zzz.txt");
Pathを生成するのにFileを使うことも出来る。
import java.io.File; import java.nio.file.Path;
Path path = new File("C:/temp/zzz.txt").toPath(); // File file = path.toFile();
Filesクラスにファイルを扱うメソッドが色々用意されている。
Filesクラスでは、ファイルやディレクトリーの指定をPathで行う。
import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.nio.file.StandardOpenOption;
例 | 説明 | 備考 | |||||||
---|---|---|---|---|---|---|---|---|---|
ファイルコピー | Path src = 〜; |
ファイルをコピーする。 正常に終了すると、コピー先ファイルのPathが返ってくる。 コピー元ファイルが無ければNoSuchFileException、 コピー先ファイルが存在していたらFileAlreadyExistsException が発生する。 |
JDK1.6以前は、自分でコピーロジックを書く必要があった。 →チャネルを使ってコピーする方法 |
||||||
Path src = 〜; |
コピーオプションは可変長引数になっており、複数のオプションを指定できる。
|
||||||||
ファイル移動 | Path src = 〜; |
ファイルを移動する。 | File#renameTo() | ||||||
ファイルからストリームへ出力 |
try (OutputStream
os = 〜) { |
ファイルの内容をOutputStreamへ出力する。 戻り値はファイルサイズ。 |
|||||||
ストリームからファイルへ出力 |
try (InputStream is =
〜) { |
InputStreamからファイルへ出力する。 戻り値はファイルサイズ。 |
|||||||
バイナリファイルの読み込み | Path src = 〜; |
ファイルを読み込む。 | |||||||
Path src = 〜; |
ファイル内の全データをバイト配列に読み込む。 | →JDK1.6以前で全データを読み込む方法 | |||||||
バイナリファイルの書き込み | Path dst = 〜; |
ファイルへ書き込む。 (このメソッドでは出力先ファイルが既に存在していてもエラーにならない模様) |
|||||||
byte[] bytes = 〜; |
バイト配列の全データをファイルに書き込む。 戻り値は出力先ファイル名。 (このメソッドでは出力先ファイルが既に存在していてもエラーにならない模様) |
→JDK1.6以前で全データを書き込む方法 | |||||||
テキストファイルの読み込み | Path src = 〜; |
テキストファイルを読み込む。 | |||||||
Path src = 〜; |
UTF8の場合はCharsetを省略できる。(JDK1.8以降)[2014-04-29] | ||||||||
Path src = 〜; |
テキストファイルの全行を読み込む。 | →JDK1.6以前で全テキストを読み込む方法 | |||||||
Path src = 〜; |
UTF8の場合はCharsetを省略できる。(JDK1.8以降)[2014-04-29] | ||||||||
Path src = 〜; |
テキストファイルの全行をStreamとして読み込む。(JDK1.8以降)[2014-04-29] | →BufferedReaderのlines() | |||||||
Path src = 〜; |
UTF8の場合はCharsetを省略できる。[2014-04-29] | ||||||||
Path src = 〜; |
テキストファイルをひとつのStringとして読み込む。(Java11以降)[2018-10-01] | ||||||||
テキストファイルの書き込み | Path dst = 〜; |
テキストをファイルへ書き込む。 (このメソッドでは出力先ファイルが既に存在していてもエラーにならない模様) |
|||||||
Path dst = 〜; |
UTF8の場合はCharsetを省略できる。(JDK1.8以降)[2014-04-29] | ||||||||
List<String> list = 〜; |
全テキストをファイルへ書き込む。 戻り値は出力先ファイル名。 (このメソッドでは出力先ファイルが既に存在していてもエラーにならない模様) |
→JDK1.6以前で全テキストを書き込む方法 | |||||||
List<String> list = 〜; |
UTF8の場合はCharsetを省略できる。(JDK1.8以降)[2014-04-29] | ||||||||
Path dst = 〜; |
文字列をファイルへ書き込む。(Java11以降)[2018-10-01] |
StandardOpenOption |
READ |
読み込む為にオープンする。 |
WRITE |
書き込む為にオープンする。 | |
APPEND |
追記する為にオープンする。 | |
TRUNCATE_EXISTING |
WRITEでのオープン時に、ファイルが既に存在していたら中身をクリアする。READでは無効。 | |
CREATE |
ファイルが無かったら作成する。 | |
CREATE_NEW |
ファイルを作成する。既に存在していたらエラー。 | |
DELETE_ON_CLOSE |
クローズ時にファイルを削除する。(ベストエフォートであり、即時に削除されるわけではない) | |
SPARSE |
||
SYNC |
データまたは属性を更新する度にストレージデバイスに対して同期をとる。 | |
DSYNC |
データを更新する度にストレージデバイスに対して同期をとる。 | |
LinkOption |
NOFOLLOW_LINKS |
シンボリックリンクをフォローしない。 |
newOutputStream(およびnewBufferedWriter)メソッドでは、(CREATE
だけ指定して)TRUNCATE_EXISTING
を指定しなかった場合、既存ファイルの内容が残るので要注意![2015-05-05]
例えば、既存ファイルの内容が「abcdef」で、新しく「123」を書き込んだとすると、「123def」になってしまう!
newOutputStream(およびnewBufferedWriter)メソッドでは、OpenOptionを何も指定しないとCREATE
・TRUNCATE_EXISTING
・WRITE
が指定された扱いになるので、むしろ何も指定しない方が安全かも(苦笑)
例 | 説明 | 備考 | |
---|---|---|---|
ディレクトリー作成 |
import java.nio.file.attribute.FileAttribute; import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.PosixFilePermissions;
|
ディレクトリーを作成する。 Windowsでは(POSIX準拠じゃないので)属性の指定は出来ない。 (Windowsで使おうとすると例外が発生する) |
File#mkdirs() |
Path dir = 〜; |
ディレクトリーを作成する。 戻り値は作成されたディレクトリー名。 |
||
Path dir = 〜; |
ディレクトリーを作成する。 親ディレクトリーが存在しない場合はNoSuchFileExceptionが発生する。 |
File#mkdir() | |
ファイル作成 | Path dst = 〜; |
空のファイルを作成する。 既に存在している場合はFileAlreadyExistsExceptionが発生する。 |
File#createNewFile() |
リンク作成 | Path link = 〜; |
リンクを作成する。 戻り値は作成されたリンク名。 既に存在している場合はFileAlreadyExistsExceptionが発生する。 |
|
シンボリックリンク作成 | Path link = 〜; |
シンボリックリンクを作成する。 Windowsは対応していない。 |
|
テンポラリーディレクトリー作成 | createTempDirectory | ||
テンポラリーファイル作成 | createTempFile | File#createTempFile() | |
ファイル・ディレクトリー削除 | Path dst = 〜; |
ファイル・ディレクトリーを削除する。戻り値は無し。 削除対象が無い場合はNoSuchFileExceptionが発生する。 ディレクトリーの場合、中が空でないとDirectoryNotEmptyExceptionが発生する。 |
File#delete() |
Path dst = 〜; |
ファイル・ディレクトリーが存在する場合だけ削除する。 削除した場合はtrue、削除対象が無かった場合はfalseが返る。 ディレクトリーの場合、中が空でないとDirectoryNotEmptyExceptionが発生する。 |
||
ファイル・ディレクトリー一覧取得 |
import java.nio.file.DirectoryStream; Path dir = 〜; |
指定されたパス直下のファイルやディレクトリー一覧を取得する。[2014-04-29] | |
Path dir = 〜; |
第2引数でファイル名のパターンを指定することが出来る。[2014-04-29] | ||
Path dir = 〜; |
フィルタークラスを渡せば、複雑なパターンにも対応できる。[2014-04-29] | ||
Path dir = 〜; |
このフィルターは関数型インターフェースなので、 JDK1.8以降ならラムダ式で書ける。[2014-04-29] |
||
import java.util.stream.Stream;
|
JDK1.8の場合、ディレクトリー直下の一覧を取得するならlist()の方が簡単。[2014-04-29] (サブディレクトリーも含めたい場合はwalk()を使う) |
||
ファイル・ディレクトリー階層取得 |
import java.nio.file.FileVisitResult; import java.nio.file.FileVisitor; import java.nio.file.attribute.BasicFileAttributes;
|
サブディレクトリー内も含めてファイル・ディレクトリー一覧を取得する。[2014-04-29]
FileVisitorを渡すとファイルやディレクトリーのパスを受け取れるので、
なお、デフォルトではシンボリックリンクのリンク先は探索対象にならない。[2015-04-18] |
|
Path dir = 〜; |
サブディレクトリーの最大階層を指定して一覧を取得する。[2014-04-29] | ||
Path dir = 〜; |
UNIXのシンボリックリンクのリンク先も含めて探索する。[2015-04-18] (参考: opengl-8080さんのシンボリックリンクのフォルダも再帰対象にする) |
||
import java.util.stream.Stream;
|
findメソッドの場合、最小限の判定用関数だけを渡せる。(JDK1.8以降)[2014-04-29] | ||
import java.util.stream.Stream;
|
JDK1.8の場合、サブディレクトリー内も含めた一覧取得はwalk()の方が簡単。[2014-04-29] →マルチスレッドで処理する例 |
||
Path dir = 〜; |
サブディレクトリーの最大階層を指定して一覧を取得する。[2014-04-29] maxDepthに1を指定すると、list()と同等になる。 |
||
Path dir = 〜; |
UNIXのシンボリックリンクのリンク先も含めて一覧を取得する。[2015-04-18] | ||
Path dir = 〜; |
Path(ファイルやディレクトリー)の属性を取得・設定するメソッドもFilesのstaticメソッドとして用意されている。
データのクラス | 取得メソッド | 設定メソッド | 説明 | 備考 | |
---|---|---|---|---|---|
属性 | Object | getAttribute | setAttribute | ||
FileAttributeView | getFileAttributeView | ||||
BasicFileAttributes | readAttributes | ||||
Map<String,Object> | readAttributes | ||||
ファイル権限 | Set<PosixFilePermission> | getPosixFilePermissions | setPosixFilePermissions | ||
所有者 | UserPrincipal | getOwner | setOwner | ||
シンボリックリンク | boolean | isSymbolicLink | |||
ディレクトリー | boolean | isDirectory | File#isDirectory() | ||
boolean | isRegularFile | File#isFile() | |||
最終更新時刻 | FileTime | getLastModifiedTime | setLastModifiedTime | File#lastModified() File#setLastModified() |
|
ファイルサイズ | long | size | ファイルサイズ(バイト単位) | ||
ファイルの存在チェック | boolean | exists | File#exists() | ||
boolean | notExists | ||||
読込可能 | boolean | isReadable | File#canRead() File#setReadable() |
||
書込可能 | boolean | isWritable | File#canWrite() File#setWritable() File#setReadOnly() |
||
実行可能 | boolean | isExecutable | File#canExecute() File#setExecutable() |
||
隠しファイル | boolean | isHidden | File#isHidden() | ||
ファイルタイプ | String | probeContentType | |||
Path | readSymbolicLink | ||||
比較 | boolean | isSameFile | 2つのPathが同じ場所を指しているかどうかをチェックする。 (ファイルの内容が同じかどうかをチェックするわけではない) |
||
long | mismatch | ファイルの内容が同じかどうかチェックする。[2019-03-31] 違う場合、違う箇所(位置)を返す。 等しい場合は-1を返す。 |
Java12 |
JDK1.7で(Closeableインターフェースと似たような)java.lang.AutoCloseableインターフェースが追加された。
AutoCloseableを実装しているクラスの場合、リソース付きtry文が使える。
CloseableもAutoCloseableを継承する形になっているので、Closeableを実装しているクラスは全てリソース付きtry文が使えることになる。
したがってJDK1.7のInputStreamやOutputStreamはリソース付きtry文を使える。
Closeable(JDK1.5)の例 | AutoCloseableの例 |
---|---|
InputStream is = 〜; try { //isを使った処理 } finally { is.close(); } |
try (InputStream is = 〜) { //isを使った処理 } |
InputStream is = 〜; try { OutputStream os = 〜; try { //is,osを使った処理 } finally { os.close(); } } finally { is.close(); } |
try (InputStream is = 〜; OutputStream os = 〜) { //is,osを使った処理 } |
ちなみに、Closeableで定義されているメソッドは投げられる例外が「public void close() throws IOException
」だが
AutoCloseableで定義されているメソッドは「public void close() throws Exception
」であることに注意。
たぶん、入出力(I/O)でないリソースについても使用できるという意味なのだろう。
ただし、オーバーライドしたメソッド側では発生させる例外の種類を減らすことが出来るので、常にException全部が指定される(指定しなければならない)というわけではない。
例えばInputStreamは以下のような形で、close()にはIOExceptionしか指定していない。
public abstract class InputStream implements Closeable { // CloseableとAutoCloseableのclose()をオーバーライド public void close() throws IOException; }