Goldの出題範囲がとても広い(なんとしても2018/9中に取りたい)。。
今回のメモはこれ。
- Fileクラス
- ストリーム
- シリアライズ
- コンソール
Fileクラス
サンプル実行のために事前にファイル作成しておく。
mkdir /tmp/dir
touch /tmp/dir/hoge.txt
touch /tmp/dir/fuga.txt
mkdir /tmp/dir/subdir
touch /tmp/a.txt
touch /tmp/dir/x.txt
import java.io.File;
public class InOutFileSample {
public static void main(String[] args) {
// Fileオブジェクトの生成
File f1 = new File("/tmp/dir");
File f2 = new File("tmp", "a.txt");
File f3 = new File(f1, "x.txt");
for (File f : f1.listFiles()) { // f1ディレクトリ内のファイル群を取得
if (f.isFile()) { // ファイルだった場合
System.out.println("File: " + f.getName());
} else if (f.isDirectory()) { // ディレクトリだった場合
System.out.println("Directory: " + f.getName());
}
}
// 絶対パス確認
System.out.println("f1 absolute path: " + f1.getAbsolutePath());
System.out.println("f2 absolute path: " + f2.getAbsolutePath());
System.out.println("f3 absolute path: " + f2.getAbsolutePath());
}
}
ストリーム
4つの基本的なストリーム
- 入力ストリーム(InputStream)
- データの読み込み
- 出力ストリーム(OutputStream)
- データの書き込み
- バイトストリーム
- byte単位で読み書きするストリーム
- キャラクタストリーム
- char単位で読み書きするストリーム
バイトストリーム | キャラクタストリーム | |
---|---|---|
出力ストリーム | OutputStream | Writer |
入力ストリーム | InputStream | Reader |
XXStreamのStreamがついてなければキャラクタストリーム。
主なバイトストリーム
クラス名 | 説明 |
---|---|
FileInputStream | ファイルからbyte単位の読み出しのためのストリーム |
FileOutputStream | ファイルに対してbyte単位の書き出しするためのストリーム |
DataInputStream | 基本データ型のデータを読み出せるストリーム |
DataOutputStream | 基本データ型のデータを書き出せるストリーム |
主なキャラクタストリーム
クラス名 | 説明 |
---|---|
FileReader | ファイルからchar単位の読み込みをするためのストリーム |
FileWriter | ファイルに対してchar単位の書き込みをするためのストリーム |
BufferedReader | 基本データ型のデータを読み込むためのストリーム |
BufferedWriter | 基本データ型のデータを書き出すためのストリーム |
FileInputStream/FileOutputStream
バイトストリームのFileInputStream
とFileOutputStream
を使った実装。
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileInputOutputStreamSsample {
public static void main(String[] args) {
try (FileOutputStream fos = new FileOutputStream("/tmp/lesson.txt");
FileInputStream fis = new FileInputStream("/tmp/lesson.txt")) {
// ファイルへの書き込み
fos.write(0);
fos.write("makio".getBytes());
fos.write(99);
// ファイルから読み込み
int data = 0;
while ((data = fis.read()) != -1) { // -1を返すまでreadメソッドでバイト単位の読み込み
System.out.print(data + " ");
}
} catch (FileNotFoundException e) {
System.out.println("ファイルがありません。");
} catch (IOException e) {
System.out.println("ファイルの読み書きで失敗");
}
}
}
0 109 97 107 105 111 99
なお、FileOutputStream
でファイルに対して追記したい場合は、以下のようにする。
// これだと新規作成になる。
FileOutputStream("/tmp/lesson.txt")
// 第二引数にtrueを与えると追記になる。
FileOutputStream("/tmp/lesson.txt", true)
DataInputStream/DataOutputStream
バイトストリームのDataInputStream
とDataOutputStream
を使った実装。
このストリームは単体では利用できないので、他のストリームと組み合わせて利用する。
import java.io.*;
public class DataInputOutputStreamSample {
public static void main(String[] args) {
try(DataOutputStream dos =
new DataOutputStream(new FileOutputStream("/tmp/lesson.txt"));
DataInputStream dis =
new DataInputStream(new FileInputStream("/tmp/lesson.txt"))) {
// ファイルへの書き込み
dos.writeInt(100);
dos.writeUTF("makio");
dos.writeUTF("ほげほげほげ");
// ファイルから読み込み
System.out.println(dis.readInt());
System.out.println(dis.readUTF());
System.out.println(dis.readUTF());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
100
makio
ほげほげほげ
FileReader/FileWriter
キャラクタストリームのFileReader
とFileWriter
クラスの利用例。
DataInputStream
/DataOutputStream
と異なり、自動でエンコーディングしてくれる。
import java.io.*;
public class FileReaderWriterSample {
public static void main(String[] args) {
try (FileWriter fw = new FileWriter(new File("/tmp/lesson.txt"));
FileReader fr = new FileReader(new File("/tmp/lesson.txt"))) {
// ファイルへの書き込み
fw.write("ほげほげほほげ");
fw.flush();
// ファイルから読み込み
int i = 0;
while((i = fr.read()) != -1) {
// キャラクタ型にキャストして出力
System.out.print((char) i);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
ほげほげほほげ
BufferedReader/BufferedWriter
キャラクタストリームのBufferedReader
とBufferedWriter
クラスの利用例。
文字列をブロック単位で読み書きするためのストリーム。
バッファリングしながら入出力するので、効率がいい。
import java.io.*;
public class BufferedReaderWriterSample {
public static void main(String[] args) {
try (BufferedWriter bw = new BufferedWriter(new FileWriter(new File("/tmp/lesson.txt")));
BufferedReader br = new BufferedReader(new FileReader(new File("/tmp/lesson.txt")))) {
// ファイルへの書き込み
bw.write("Good morning!");
bw.newLine();
bw.write("Good afternoon!");
bw.newLine();
bw.write("Good evening!");
bw.flush(); // flushで即時反映
// ファイルから読み込み
String data = null;
while ((data = br.readLine()) != null) { // readLineメソッドはファイルの最後になると、nullを返す。
System.out.println(data);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Good morning!
Good afternoon!
Good evening!
シリアライズ
- シリアライズ
- オブジェクトを出力ストリームに書き出すこと
- 直列化ともいう。
- デシリアライズ
- シリアライズされたオブジェクトを読み込んでメモリ上の復元すること
- 直列化復元ともいう。
シリアライズの方法
ここではUser
クラスのオブジェクトをObjectInputStream
とObjectOutputStream
を使ってファイルに書き出して復元する。
import java.io.*;
/**
* シリアライズ対象のUserクラス
* Serializableインタフェースはメソッドをもたない
*/
class User implements Serializable {
private int id;
private String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
}
public class SerializeDeseriazlieSample {
public static void main(String[] args) {
User writeUser = new User(1000, "Makio");
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("/tmp/user_object.txt"));
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("/tmp/user_object.txt"))) {
// オブジェクトの書き込み シリアライズ
oos.writeObject(writeUser);
oos.flush();
// オブジェクトの読み込み デシリアライズ
User readUser = (User)ois.readObject(); // Userにキャストしないといけない。
System.out.format("id: %d, name: %s", readUser.getId(), readUser.getName());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
id: 1000, name: Makio
シリアライズの注意点
考えて見れば当たり前ことばかりだけど制約事項が多い。
- 配列またはコレクションをシリアライズする場合は、その要素のそれぞれがシリアライズ可能でないといけない。
- シリアライズされたオブジェクトが参照しているオブジェクトもシリアライズ可能でないといけない.
-
static
変数およびtansient
指定された変数はシリアライズ対象外になる。 - スーパークラスをシリアライズ対象としていればサブクラスも暗黙的にシリアライズ対象になる。
- サブクラスがシリアライズ対象の場合、スーパークラスはデシリアライズの際にインスタンス化される。
コンソール
コンソールから読み書きするためにはConsole
オブジェクトを生成してコンソールのストリームに読み書きする。
import java.io.Console;
import java.io.PrintWriter;
public class ConsoleSample {
public static void main(String[] args) {
// System.console()で一意のConsoleオブジェクトを取得
// コンソールが使用できない場合はconsole()メソッドはnullになる。
Console console = System.console();
// キャラクタストリームのPrintWriterオブジェクトを生成
PrintWriter pw = console.writer();
while (true) {
String str = console.readLine();
if (str.equals("end")) {
break;
}
pw.append("input data: " + str);
pw.flush();
}
}
}