Ch9. NIO2

Pathクラス

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;

public class TryNIO2 {
    public static void main(String[] args) throws IOException {
        Path pathToTextFile = Paths.get("C:", "Users", "broad", "Desktop","test.txt");
        System.out.println(pathToTextFile);//'C:\Users\broad\Desktop\test.txt'
        System.out.println(pathToTextFile.getFileName());//'test.txt'
        System.out.println(pathToTextFile.getName(2));//'Desktop'
        System.out.println(pathToTextFile.getNameCount());//'4'
        System.out.println(pathToTextFile.getParent());//'C:\Users\broad\Desktop'
        System.out.println(pathToTextFile.subpath(1,3));//'broad\Desktop'
        System.out.println(Paths.get(".").toRealPath());//'C:\Users\broad\IdeaProjects\JavaSilverPractice'
        System.out.println(pathToTextFile.getRoot());//'C:\'
        System.out.println(pathToTextFile.isAbsolute());//'true'
        System.out.println(pathToTextFile.relativize(Paths.get("C:", "Users", "broad")));//'..\..'
        System.out.println(pathToTextFile.toUri());//'file:///C:/Users/broad/Desktop/test.txt'

        Path pathFirst = Paths.get("C:", "Users");
        Path pathLast  = Paths.get( "broad", "Desktop");
        System.out.println(pathFirst.resolve(pathLast));//'C:\Users\broad\Desktop'
        System.out.println(pathFirst.resolve(pathToTextFile));//'C:\Users\broad\Desktop\test.txt'
    }
}
  • getName()ではルート(C:)にもっとも近い要素を【0】として引数で渡されたパス要素を返却している。
  • getNameCount()ではルート要素を除いたパス内の要素数を返却している。
  • subpath(x, y)ではx個目のパス要素から【y-1】個目のパス要素までを返却する。
  • toRealPathではカレントディレクトリから完全パスを取得している。正常なディレクトリではない場合検査例外のIOExceptionが返される。
  • resolve(Path x)はパス同士の連結を行う。ただし、引数に指定されたPathが完全パスだった場合、引数で指定されたPathがそのまま返却される。

Filesクラス

staticメソッドしか存在しないユーティリティクラス。

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class TryFileUtil {
    public static void main(String args[]) {
        Path pathToTextFile = Paths.get("C:", "Users", "broad", "Desktop","test.txt");
        System.out.println(Files.exists(pathToTextFile));//'true'
        System.out.println(Files.isDirectory(pathToTextFile));//'false'
        System.out.println(Files.isRegularFile(pathToTextFile));//'true'
        System.out.println(Files.isReadable(pathToTextFile));//'true'
        System.out.println(Files.isExecutable(pathToTextFile));//'true'

        Path pathToNewDir = Paths.get("C:", "Users", "broad", "Desktop","MyStudies");
        Path pathToNewDir2 = Paths.get("C:", "Users", "broad", "Desktop","MySailing", "470");
        try {
            Files.createDirectory(pathToNewDir);
            Files.createDirectories(pathToNewDir2);//'必要な親ディレクトリを自動生成'

            Files.delete(pathToNewDir);
            Files.deleteIfExists(pathToNewDir2);//'C:\Users\broad\Desktop\MySailingは残る'
        } catch (IOException e) {
            e.printStackTrace();
        }
    };
}
  • createDirectoryに対してcreateDirectoriesはPathで指定されたディレクトリのために必要な親ディレクトリを生成してくれる。
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

public class TryFileUtil {
    public static void main(String args[]) {

        Path pathToParentalDir = Paths.get("C:", "Users", "broad", "Desktop","MySailing");
        //Path pathToNewDest = Paths.get("C:", "Users", "broad", "Desktop","CopiedMySailing");
        Path pathToNewDest = Paths.get("C:", "Users", "broad", "Desktop", "MySailing","CopiedMySailing");

        try {

            boolean resultBefore = Files.exists(pathToParentalDir.resolve("test.txt"));
            System.out.println(resultBefore);
            Files.copy(pathToParentalDir, pathToNewDest, StandardCopyOption.REPLACE_EXISTING);
            boolean result = Files.exists(pathToNewDest.resolve(Paths.get("MySailing","test.txt")));
            System.out.println(result);

        } catch (IOException e) {
            e.printStackTrace();
        }
    };
}

ディレクトリのコピーを行うときは注意が必要。 コピー先のパス名にはコピーしたいディレクトリの名前を含めてやる必要がある。また、ディレクトリの中身まではコピーされない。

シンボリックリンクをコピーする際はLinkOption.NOFLLOW_LINKSを指定してやる必要がある。これが無い場合、Javaシンボリックリンクの宛先(つまりリンク元の実態)をコピーする。(指し先はそのままに)シンボリックリンクをコピーする際はこのオプションを利用する。

Filesクラスには今まで利用してきたBufferedReader等を利用せず1メソッドでファイルの中身が読み込めるクラスメソッドを用意している。

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

public class FileUtil2 {
    public static void main(String[] args){
        Path pathToParentalDir = Paths.get("C:", "Users", "broad", "Desktop","MySailing","test.txt");
        try {
            List<String> contents = Files.readAllLines(pathToParentalDir);
            contents.stream().forEach(System.out::println);
            //'千代田線'
            //'銀座線'
            //'半蔵門線'
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

listAllLinesがListで戻り値を返却するのに対して、Streamで返却されるのがlinesである。

public class DirectoryAccess2 {
    public static void main(String[] args) throws IOException {
       
        Path pathToParentalDir = Paths.get("C:", "Users", "broad", "Desktop","MySailing","470.txt");
        Files.lines(pathToParentalDir).forEach(System.out::println);
    }
}
明治
立教
法政
中央
青山

メタデータの取得

BasicFileAttributes

OSに限定されない全てのファイルシステムで保持するファイルのメタデータを扱うインターフェース。getAttributeで各属性を、readAttributesで全ての属性を一度に読み込める。

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.DosFileAttributes;

public class TryFileUtil {
    public static void main(String args[]) {

        Path pathToParentalDir = Paths.get("C:", "Users", "broad", "Desktop","MySailing","470.txt");

        try {
            System.out.println( Files.getAttribute(pathToParentalDir, "creationTime"));
            System.out.println( Files.getAttribute(pathToParentalDir, "lastModifiedTime"));
            System.out.println( Files.getAttribute(pathToParentalDir, "size"));

            BasicFileAttributes attr = Files.readAttributes(pathToParentalDir, BasicFileAttributes.class);
            System.out.println(attr.creationTime());
            System.out.println(attr.lastModifiedTime());
            System.out.println(attr.size());

            DosFileAttributes attrDos = Files.readAttributes(pathToParentalDir, DosFileAttributes.class);
            System.out.println(attrDos.isArchive());
            System.out.println(attrDos.isHidden());
            System.out.println(attrDos.isReadOnly());
            System.out.println(attrDos.isSystem());
            System.out.println(attrDos.lastModifiedTime());

        } catch (IOException e) {
            e.printStackTrace();
        }
    };
}

readAttributesメソッドは第二引数にインターフェースを指定する変わった使い方をする。 代入先の変数のインターフェースも、各ファイルシステム共通のBasicFileAttributresDOSファイルシステム専用のDosFileAttributesが存在する。

ディレクトリ操作

ルートディレクトリとはC:\とかD:\とかで取得できるもので、複数存在する前提でSteramオブジェクトとして取得できる。 取得にはFileSystemsクラスを利用する。

同様にディレクトリ内の内容もStreamオブジェクトとしてFilesクラスのnewDirectoryStreamで取得することが出来る。

public class DirectoyAccess {
    public static void main(String[] args) throws IOException {
        FileSystem fs = FileSystems.getDefault();
        fs.getRootDirectories().forEach(System.out::println);

        Path pathToParentalDir = Paths.get("C:", "Users", "broad", "Desktop","MySailing");
        System.out.println("newDirectoryStream");
        Files.newDirectoryStream(pathToParentalDir).forEach(System.out::println);

        System.out.println("work");
        Files.walk(pathToParentalDir).forEach(System.out::println);

        System.out.println("list");
        Files.list(pathToParentalDir).forEach(System.out::println);
    }
}
C:\
newDirectoryStream
C:\Users\broad\Desktop\MySailing\470.txt
C:\Users\broad\Desktop\MySailing\49er.txt
C:\Users\broad\Desktop\MySailing\LaserRadial.txt
C:\Users\broad\Desktop\MySailing\Ports
work
C:\Users\broad\Desktop\MySailing
C:\Users\broad\Desktop\MySailing\470.txt
C:\Users\broad\Desktop\MySailing\49er.txt
C:\Users\broad\Desktop\MySailing\LaserRadial.txt
C:\Users\broad\Desktop\MySailing\Ports
C:\Users\broad\Desktop\MySailing\Ports\abuzuri.txt
list
C:\Users\broad\Desktop\MySailing\470.txt
C:\Users\broad\Desktop\MySailing\49er.txt
C:\Users\broad\Desktop\MySailing\LaserRadial.txt
C:\Users\broad\Desktop\MySailing\Ports

newDirectoryStreamlist``で取得したStreamは指定したパスの直下しか探さないのに対して、work```で取得したStreamはリクルーシブに検索している。

newDirectoryStreamlistの違いは戻り値の型がDirectoryStream<Path>Stream<Path>である点。

先ほど確認したBasicFileAttributesを検索条件に指定することも可能。検索条件による絞り込みを行うにはfindメソッドを利用する。

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class DirectoryAccess2 {
    public static void main(String[] args) throws IOException {
        Path path = Paths.get("C:", "Users", "broad", "Desktop","MySailing");
        Files.find(path,10, (thispath, attr) -> (thispath.toString().endsWith(".txt") && attr.creationTime().toMillis() > 0)).forEach(System.out::println);
    }
}
C:\Users\broad\Desktop\MySailing\470.txt
C:\Users\broad\Desktop\MySailing\49er.txt
C:\Users\broad\Desktop\MySailing\LaserRadial.txt
C:\Users\broad\Desktop\MySailing\Ports\abuzuri.txt