【JavaGold】入出力

# 入出力

### java.io.File
パスを扱っているだけであって、ファイルやディレクトリそのものを表すわけではない。

```java:実装例
Path path = new File("sample.txt").toPath();
```

#### listFilesメソッド
ディレクトリ内の一覧をFileとして取得。

```
/path/to/directory/
    ├── file1.txt
    ├── file2.txt
    └── subdirectory/
        ├── file3.txt
        └── file4.txt
```

```java:実装例
import java.io.File;

public class ListFilesExample {
    public static void main(String[] args) {
        // ディレクトリパスを指定してFileオブジェクトを作成
        // File 変数 = new File(調べたいディレクトリのパス);
        File directory = new File("/path/to/directory");

        // ディレクトリ内のファイルとディレクトリの一覧を取得
        File[] files = directory.listFiles();

        // 取得した一覧を表示
        if (files != null) {
            for (File file : files) {
                System.out.println(file.getName());
            }
        } else {
            System.out.println("ディレクトリが存在しないか、空です。");
        }
    }
}
```
この例では、/path/to/directoryに指定されたディレクトリ内のファイルとディレクトリの一覧を取得し、それらの名前を表示する。

```:実行結果
file1.txt
file2.txt
subdirectory
```

### java.io.Reader
テキストデータを読み込みためクラス。

### java.io.BufferedReader
#### readLine()
キーボードからの入力をバイトストリームとして受け取り、それを文字ストリームに変換して文字列を戻す。

```java:実装例
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Sample {
    public static void main(String[] args) {
        try (BufferedReader br
                = new BufferedReader(
                    new InputStreamReader(System.in))) {
            System.out.println(" in : ");
            String input = br.readLine();
            System.out.println(" out: " + input);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
```
```:実行コマンド
java Sample hello
```
```:実行結果
プログラム実行中に入力待ちになる
```

起動パラメータは、プログラムの実行時にデータを入力し、mainメソッドの引数として渡されるもので、プログラム実行中にキーボード入力として取り出せるものではない。


### java.io.BufferedInputStream
写真データを読み込むために使用するクラス。
#### readAllBytes()
すべてのバイトを一度に読み込む。


### java.io.FileWriter
文字を書き込むためのクラス。

```java:実装例
FileWriter filewriter = new FileWriter("output.txt", false);
```
falseを渡した場合は、上書きモードで書き込む。trueを渡した場合、ファイルの最後に追記する。

### java.io.BufferedWriter
flushメソッドはバッファとファイルを同期させる。

### java.io.Console
#### `readLine()`
キーボードからの入力を受け取ることができる。

#### `readPassword()`
* メソッドの戻り値の型はchar[]。
* 入力した内容は機密情報であるパスワードとして扱われ、コンソールに表示せず受け取れる。System.out.printlnを使用すれば、文字列がそのまま表示される。

### java.util.Scanner

```java:実装例
import java.util.Scanner;

public class Exe {
    public static void main(String[] args) {
        Scanner scan = new Scanner("A,B,C,D,E");
        // 読み込み時の区切り文字を変更
        scan.useDelimiter(",");

        try (scan) {
            scan.next();
            scan.next();
            scan.next();
            scan.next();
            System.out.println(scan.next());
            
        } 
    }
}
```
```:実行結果
E
```

### java.io.Serializable
このインタフェースには、何もメソッドが定義されていない。

カスタム・シリアライズを行うときに、シリアライズ時に呼び出されるメソッドは、writeObjectメソッド。

### java.nio.file.Path
ファイルやディレクトリへのパスを表す。

### java.nio.file.Paths

#### Path get(String first, String... more)
1つのパス文字列または、連結すると1つのパス文字列を形成する文字列のシーケンスを、Pathに変換します。

```java:実装例
Path path = Paths.get("sample.txt");
// 相対パスの指定も可
Path path = Paths.get("dir/sample.txt");
Path path = Paths.get("dir", "sample.txt");
```

#### `resolve()`
2つのPathインスタンスを結合して新しいPathインスタンスを作成する。

```java:実装例
Path p1 = Paths.get("C:/data/image");
Path p2 = Paths.get("photo/profile.jpg");

Path p3 = p1.resolve(p2);
System.out.println(p3);
```

```:実行結果
C:\data\image\photo\profile.jpg
```

#### `normalize()`
normalize() はパス中に含まれる .(現在のディレクトリ) および ..(親ディレクトリ) という名前を除去することで正規化します。

```java:実装例①
Path dir = Path.of("./a/b/../c");
dir.normalize();
```

```:実行結果
a/c
```

```java:実装例②
Path.of("./a/b/../../../../").normalize();
```

```:実行結果
../..
```

### java.nio.file.Files
ファイルの操作クラス

```java:実装例
package innerclass;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Scanner;

public class Sample {
	public static void main(String[] args) throws Exception{
		System.out.print(">");
		// Scannerクラスのインスタンスを作成し、キーボードから入力された文字列や数値を受け取って、処理する
		Scanner scan = new Scanner(System.in);
		String name = scan.nextLine();
		// dirディレクトリ配下のファイル(コンソールで指定)のパスを取得
		Path p = Paths.get("dir", name);

		// もし指定したファイルが存在しなければ、新しくファイルを作成
		if(Files.exists(p) == false) {
			Files.createFile(p);
		}
	}
}
```

コンソールにaを入力しているのでaのファイルが作成。

java.nio.file.Filesクラスを使用してファイルを作成する場合、既存と同じファイルパスにすると、例外でスローされる。

* ファイルのコピーを行うには、copyメソッドを使う。
* ファイルの移動するにはmoveメソッドを行う。
* 引数で渡したディレクトリの中にさらにサブディレクトリがあったとき、その中まですべて再帰的に探索するメソッドはwalkメソッド。

java.nio.file.Filesクラスを使い、java.io.BufferedWriterを追記モードで取得。

```java:実装例
Path sample = Paths.get("sample.txt");
BufferedWriter out 
    = Files.newBufferedWriter(
        sample
        ,StandardOpenOption.APPEND);
```

<table>
  <caption>StandardOpenOptionの主な定数</caption>
  <thead>
    <tr>
      <th>定数</th>
      <th>意味</th>
    </tr>
  </thead>
  <tr>
    <td>APPEND</td>
    <td>追記モードでファイルを開く。</td>
  </tr>
  <tr>
    <td>CREATE</td>
    <td>ファイルが存在しない場合は新しいファイルを作成する。</td>
  </tr>
  <tr>
    <td>CREATE_NEW</td>
    <td>新しいファイルを作成し、ファイルがすでに存在する場合は失敗する。</td>
  </tr>
  <tr>
    <td>DELETE_ON_CLOSE</td>
    <td>閉じるときに削除する。</td>
  </tr>
  <tr>
    <td>READ</td>
    <td>読み込みアクセス用に開く。</td>
  </tr>
</table>

#### createFile()
新しいファイルを作成。

#### createDirectory()
親ディレクトリがなければ例外が発生。

```java:実装例
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.Files;
import java.io.IOException;

class createDirectorySample {
  public static void main(String[] args) {
    Path p = Paths.get("C:/code/java/file/doc");

    try {
      Files.createDirectory(p);
    } catch(IOException e) {
      System.out.println(e);
    }
  }
}
```

```:実行結果
docというディレクトリを作成される
```

#### createDirectories()
親ディレクトリが存在しなくても、サブディレクトリを作成。

```java:実装例
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.Files;
import java.io.IOException;

class createDirectoriesSample {
  public static void main(String[] args) {
    Path p = Paths.get("C:/code/java/file/doc/manual/back");

    try {
      Files.createDirectories(p);
    } catch(IOException e) {
      System.out.println(e);
    }
  }
}
```
```:実行結果
すべてのディレクトリが作成される
```

#### `deleteIfExists()`
パスや表現されるファイルやディレクトリが存在すれば削除し、削除したかどうかをboolean型の結果で戻す。

```java:実装例(sample.txtが存在しない場合)
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class Sample {
  public static void main(String[] args) {
    try {
        Path path = Paths.get("sample.txt");
        boolean result = Files.deleteIfExists(path);
        if (result) {
            System.out.println("A");
        } else {
            System.out.println("B");
        }
    } catch(IOException e) {
      System.out.println("C");
    }
  }
}
```
```:実行結果
B
```

#### `Path move(Path, Path)`
指定されたパスからパスへ移動、またはリネームする。
```java:実装例:ファイルを移動
Path p1 = Paths.get("src/file1.txt");
Path p2 = Paths.get("dest/file2.txt");

try{
    Files.move(p1, p2);
} catch(IOException e) {
    System.out.println(e);
}
```
カレントディレクトリの下にある src ディレクトリの中の file1.txt ファイルを、カレントディレクトリの下の dest ディレクトリの中に移動し file2.txt という名前に変更します。
この時、移動先のファイルが既に存在していた場合は java.nio.file.FileAlreadyExistsException 例外が発生。

```java:実装例:ディレクトリの移動
Path p1 = Paths.get("src");
Path p2 = Paths.get("dest");

try{
    Files.move(p1, p2);
} catch(IOException e) {
    System.out.println(e);
}
```

ディレクトリを移動元として指定した場合、移動先に指定したディレクトリが作成されます。移動元のディレクトリが空ではなかった場合、移動元のディレクトリに格納されていたファイルやサブディレクトリ(およびサブディレクトリに格納されているファイルなど)は移動先のディレクトリの中に移動します。
この時、移動先のディレクトリが既に存在している場合は java.nio.file.FileAlreadyExistsException 例外が発生。


####  public static Stream< String> lines​(Path path)
ファイル内のすべての行を読み込み、Streamとして戻す。
```java:実装例
var a = Files.lines(Paths.get(fileName))
```

####  List<String> readAllLines(Path path)
ファイル内のすべての行を読み込み、Listとして戻す。
```java:実装例
var a = Files.readAllLines(Paths.get(fileName))
```

### FileVisitorインタフェース

FileVisitorインタフェースには、処理タイミングが異なる以下の4つの抽象メソッドが含まれており、全て実装する必要がある。

1\. preVisitDirectory(Path dir, BasicFileAttributes attrs);
　ディレクトリに入る前に実行される。

2\. postVisitDirectory(Path dir, IOException exc)：
　ディレクトリを出た後に実行される。

3\. visitFile(Path file, BasicFileAttributes attrs)：
　ファイルに遭遇した時に実行される。

4\. visitFileFailed(Path file, IOException exc)：
　ファイルの処理に失敗した時に実行される。

これらのメソッドを実装することで、ファイルツリーの走査中に実行したいアクションを指定できる。