きっかけ
学校でJavaを教えているのでその時の資料から作ってみました。
語句の説明
とりあえず、語句の説明を。
FileIOってなんだよ?
ファイルシステム(file system)のI (Input / 入力) と O (Output / 出力) を行えるよ!
ファイルシステムってなんやねん!!
ファイルシステムとは、OSにおいてデータを保管するファイル(File)とそれをまとめ上げて管理するディレクトリー(Directory, Folder)で作られる世界のこと。
はじめに
FileIOで何ができるん?
ファイルとディレクトリーに対して、delete(削除), create(作成), exist(存在確認),…,write(書き込み), read(読み込み)などいろいろ、私達がOSで行うこと(たぶん)すべてができる!
じゃぁJavaでそれを行うにはどうすればいいの?
→NewIOというJavaの標準ライブラリがおすすめですよ!
旧来はFile(java.io系)というクラスを中心として構成されていたが、現在では便利で最適化されているなどの様々な利点からNew I/O(java.nio系)というパッケージを用いて行うのがこれからの主流となっています(させます)。
NewIOを使ってみよう
NewIOを始めるにあたって
NewIOでは一般的に次の2つ(3つ)のクラスが基礎的な役割を持ちます。
Path: Stringを変換してファイルのパスを表すようにしたクラス
Paths: Pathを作るためのクラス
Files: 実際にファイル操作をするクラス
※FileクラスはNewIOではなく、古のもの(NewIOでないOldなIO系)のため注意すべし。
Pathの取得
Pathの取得(例) … ファイルの場所!
Path path = Paths.get(“C:\\”, “a”);
※Pathはnewでは作れません!
※Pathsのgetメソッドはstaticメソッドです!
※getメソッドの引数は、可変長引数で、引数ごとで、ファイルの階層を表すことができます。
※パス(普通に文字列)の取得は、ファイルを選択して、Shift+右クリックで「パスのコピー」を行うと楽。
※パスは、エスケープシークエンスとダブルクオーテーションに気をつける。
Filesの利用例
Filesの利用の例 … ファイル/ディレクトリーに対する操作を行う。
Files.exsit(path);
※戻り値はbooleanなのでこれをif文で使うことができる!
ファイルへの読み書き
基本的に次の2つのクラスを使うと良い。(ほかのクラスは基本的に古のものが多いが、他人のプログラムでは古でも使われることが多いので注意?してください)
BufferedWriter: バッファを用いて効率的に、ファイルに書き込みを行うクラス
BufferedReader: バッファを用いて効率的に、ファイルに読み込みを行うクラス
Buffer(バッファ)って?
メモリ空間上に一時的に置かれたデータのこと。tmp/temp(テンプ)ともいいます。
BufferedWriter/BufferedReaderの(インスタンスの)生成
古の方法
たぶん、(NewIOでは)あんまり使わないです。
BufferedWriter bw = new BufferedWriter(Writer);
BufferedReader br = new BufferedReader(Reader);
NewIOを用いた、BufferedWriter/BufferedReaderの生成
BufferedWriter bw = Files.newBufferedWriter(path);
BufferedWriter/BufferedReaderの利用
bw.write(String);
String line = br.readLine();
※bw, brはそれぞれclose()メソッドを呼び出さないと行けない。
(why -> bwでclose()を呼び出さないと出力されない, flush()の呼び出し)
try {
BufferedWriter bw = Files.newBufferedWriter(path);
bw.write(“A”);
bw.close();
} catch (IOException ex) {
ex.printStackTrace();
}
また、closeで例外が発生する恐れがあり、closeに対する例外処理必要が必要でもある。
よって以下のようにする必要がある。
try {
BufferedWriter bw = Files.newBufferedWriter(path);
bw.write(“A”);
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
bw.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
クソ長い
BufferedWriter/BufferedReaderの利用(改良) ~ try-catch-resouce!
先程のように書くと凄く長い。そこでJava7からtry-catch-resouce構文が追加され、以下のように簡潔に書けるようになった。
try (BufferedWriter bw = Files.newBufferedWriter(path)) {
bw.write(“A”);
}
めっちゃいい。
参考: https://qiita.com/Takmiy/items/a0f65c58b407dbc0ca99
改行をするには?(write()の利用)
br.write(text)を呼び出しただけでは、改行されず、
br.write("AA");
br.write("BB");
↓
AABB
みたいなことになってしまう。
改行するには、行の文字列の最後に改行文字をつければ良い。
bw.write(text + System.lineSeparator());
※System.lineSeparator();はOS毎に正しい改行文字を返してくれるメソッド。
CRLF(\r\n), LF(\n)とかの差異に気をつけなくて良い!(改行文字については調べよう)
課題
1.ファイルに文字列を書き込む
2.「1.」の複数行version (Listを用いて)
3.ファイルの読み込み
4.「3.」の複数行version (Listを用いて行の表現), なお全ての行でも良いし、任意の範囲の行でも良い。
コラム
私達が今まで使ってきたいつもの構文について…
System.out.println(“Hello world!”);
これをFileIOを理解した上でみるとなんだかFileIOっぽいなぁと思いますよね。
どういうこと?ってなりますけど。
実は、System.out (のout)は、OutputStreamなのである!ということ。(つまり出力用)
一応、StreamというのはFileIOを抽象化したものです。(たぶん)
同様に、System.in というものもありますが、これはInputStreamです。(つまり入力用)
しかしながら、これは考えれば自然で、コンソールに文字を書くことって、実際はファイルに文字を書くこととあまり変わりないですよね(自分はこういう共通化するという所が面白いなーと思いました)。
参考/Reference
・Oracleの公式解説ページ群
・java.io.File のコードを java.nio.Path と java.nio.Files を使って書き直す
・Javaのファイル入出力関係のクラス/インタフェースについて整理する