Ch.8 入出力
Fileクラス
ファイル名やディレクトリ名の取得に用いられる。
import java.io.File; import java.util.Arrays; public class FileIO { public static void main (String args[]){ File thisDr = new File("C:\\Users\\broad\\Desktop"); Arrays.stream(thisDr.listFiles()).forEach(a -> System.out.println(a.getName()+ " isDir? : " + a.isDirectory())); //'desktop.ini isDir? : false' //'Java Gold取得計画.lnk isDir? : false' //'my-account-book isDir? : true' //'my-account-book-server isDir? : true' System.out.println("file.separator : " + System.getProperty("file.separator")); //'\' System.out.println("line.separator : " + System.lineSeparator().toUpperCase()); // System.out.println("path.separator : " + System.getProperty("path.separator")); //';' } }
ストリーム
Javaでは「ストリーム」を用いて、ファイルの中身の読み書きを行う。 「ストリーム」の利用法は主に3通り存在する。
出力クラス | 出力単位 | 備考 |
---|---|---|
FileInput/OutputStream | byte単位 | バイナリファイル向け |
DateInput/OutputStream | 基本データ型(int String)単位 | FileOutputStreamとの併用 |
FileReader/Writer | char単位 | テキストファイル向け |
BufferedReader/Writer | 文字列単位 | FileWriterとの併用 |
FileOutputStream(単体)
import java.io.*; import java.nio.charset.StandardCharsets; public class FStream { public static void main (String[] args){ try( FileOutputStream fos = new FileOutputStream(new File("C:\\Users\\broad\\Desktop\\test.txt")); FileInputStream fis = new FileInputStream (new File("C:\\Users\\broad\\Desktop\\test.txt")) ) { fos.write("もふもふの犬".getBytes(StandardCharsets.UTF_8)); int data = 0; while ((data != -1)){ System.out.println(data); data = fis.read(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } ; } }
0 227 130 130 227 129 181 227 130 130 227 129 181 227 129 174 231 138 172
DataOutputStream(FileOutputStream併用)
import java.io.*; public class DIOStream { public static void main (String[] args){ try( DataOutputStream dos = new DataOutputStream(new FileOutputStream("C:\\Users\\broad\\Desktop\\test.txt")); DataInputStream dis = new DataInputStream (new FileInputStream("C:\\Users\\broad\\Desktop\\test.txt")); ) { dos.writeInt(873); dos.writeUTF("お花見"); dos.writeUTF("花見"); System.out.println(dis.readInt()); //'873' System.out.println(dis.readUTF()); //'お花見' System.out.println(dis.readUTF()); //'130' } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } ; } }
FileReaderクラス
import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class FWriter { public static void main(String[] args){ try( FileWriter fw = new FileWriter(new File("C:\\Users\\broad\\Desktop\\test.txt")); FileReader fr = new FileReader(new File("C:\\Users\\broad\\Desktop\\test.txt"))) { fw.write("えりんぎ まつたけ ぶなしめじ");//Char単位の読み書きを扱うが、文字列も渡せる。 fw.flush(); int i = 0; while(i != -1){ i = fr.read(); System.out.println(i); System.out.println((char)i); } } catch (IOException e) { e.printStackTrace(); } } }
12360 え 12426 り 12435 ん 12366 ぎ 32 12414 ま 12388 つ 12383 た 12369 け 32 12406 ぶ 12394 な 12375 し 12417 め 12376 じ -1
BufferdReaderクラス
import java.io.*; public class BWriter { public static void main(String[] args){ try( BufferedReader br = new BufferedReader(new FileReader("C:\\Users\\broad\\Desktop\\test.txt")); BufferedWriter bw = new BufferedWriter(new FileWriter("C:\\Users\\broad\\Desktop\\test.txt")); ){ bw.write("うまい"); bw.newLine(); bw.write("やすい"); bw.newLine(); bw.write("はやい"); bw.newLine(); bw.flush(); String data = null; while((data = br.readLine()) != null){ System.out.println(data); } }catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
BufferedStreamクラスではmarkという、アンカーのようなメソッドがサポートされている。
markで設定した位置にはreset
で戻ることが出来る。
bw.write("東京品川新横浜小田原熱海三島新富士静岡"); bw.newLine(); bw.write("掛川浜松豊橋三河安城名古屋岐阜羽島米原"); bw.newLine(); bw.write("京都新大阪新神戸西明石姫路相生岡山新倉敷"); bw.newLine(); bw.flush(); String data = null; System.out.println(br.readLine());//'東京品川新横浜小田原熱海三島新富士静岡' br.mark(100); System.out.println(br.readLine());//'掛川浜松豊橋三河安城名古屋岐阜羽島米原' br.reset(); System.out.println(br.readLine());//'掛川浜松豊橋三河安城名古屋岐阜羽島米原' br.skip(4); System.out.println(br.readLine());//'阪新神戸西明石姫路相生岡山新倉敷'
markの引数としてわたしている数は「これ以上の数を読み込むと、resetで元の位置に戻ることに失敗してしまう可能性がある数」だそう。
BufferedReader (Java Platform SE 8)
Systemクラスの定数
標準入出力もStreamによって処理されている。 標準出力のStreamは各クラスの定数として存在する。
出力クラス | クラス定数名 |
---|---|
InputStream | System.in |
PrintStream | System.out |
PrintStream | System.err |
シリアライズ
import java.io.*; public class Serialize { public static void main(String[] args){ try(ObjectOutputStream objectOutStream = new ObjectOutputStream(new FileOutputStream("C:\\Users\\broad\\Desktop\\javaSerial.txt")); ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("C:\\Users\\broad\\Desktop\\javaSerial.txt")) ){ MyClass obj = new MyClass(); obj.method(); System.out.println(obj.message); objectOutStream.writeObject(obj); MyClass b = (MyClass)objectInputStream.readObject(); System.out.println(b.message); MySecondClass obj2 = new MySecondClass(); obj2.method(); System.out.println(obj2.message); objectOutStream.writeObject(obj2); MySecondClass c = (MySecondClass) objectInputStream.readObject(); System.out.println(c.message); } catch (IOException | ClassNotFoundException e ) { e.printStackTrace(); } } } class MyClass implements Serializable { public String message; MyClass(){ System.out.println("コンストラクタ"); } public void method(){ this.message = "Hello"; } } class MySecondClass extends MyClass{ @Override public void method() { this.message = "Goodbye"; } }
シリアライズで読みだすときは、そのクラスのコンストラクタが同時に呼び出される。
子クラスをシリアライズして読みだすとき、その子クラスの親クラスがSerializable
インターフェースを実装しているかどうかで挙動が異なる。
親クラスがSerializable
インターフェースを実装していない場合、読みだすときに親クラスのコンストラクタが同時に呼び出される。
package Serialize2; import java.io.*; public class Serialize2 { public static void main(String[] args){ try( ObjectOutputStream objectOutStream = new ObjectOutputStream(new FileOutputStream("C:\\Users\\broad\\Desktop\\javaSerial.txt")); ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("C:\\Users\\broad\\Desktop\\javaSerial.txt")) ){ Dictionary obj = new Dictionary(); System.out.println(obj.thisIstransent); objectOutStream.writeObject(obj); Dictionary b = (Dictionary) objectInputStream.readObject(); System.out.println(b.thisIstransent); System.out.println(b.thisIstransent2); //'親クラスのコンストラクタ' //'子クラスのコンストラクタ' //'Hello Transient' //'親クラスのコンストラクタ' //null //null Fighter obj2 = new Fighter(); objectOutStream.writeObject(obj2); Fighter c = (Fighter) objectInputStream.readObject(); System.out.println(c); //'親クラスのコンストラクタ' //'子クラスのコンストラクタ //'Serialize2.Fighter@4de8b406' } catch (IOException | ClassNotFoundException e ) { e.printStackTrace(); } } } class Book{ Book(){ System.out.println("親クラスのコンストラクタ"); } } class Dictionary extends Book implements Serializable{ public transient String thisIstransent = "Hello Transient"; public transient String thisIstransent2; Dictionary(){ System.out.println("子クラスのコンストラクタ"); thisIstransent2 = "this is also transient"; } } class Airplane implements Serializable{ Airplane(){ System.out.println("親クラスのコンストラクタ"); } } class Fighter extends Airplane implements Serializable{ Fighter(){ System.out.println("子クラスのコンストラクタ"); } }
上記のDictionaryクラスからもわかるようにtransient
キーワードのついた変数はたとえクラス内で初期化されていても、シリアライズされない。
これはコンストラクタで初期化されていても同じである。シリアライズされる際のコンストラクタの呼ばれ方は通常の呼ばれ方と異なることがわかる。
コンソール
コンソールが利用可能な端末ではSystem.console
でコンソールを取得できる。組み込みの実行環境であれば当然コンソールは存在しないためnull
が返却される。
import java.io.Console; import java.io.PrintWriter; public class ConsoleTry { public static void main(String[] args){ Console console = System.console(); String str = console.readLine(); PrintWriter writer = console.writer(); writer.append("Input : " + str); writer.flush();//'Input : hello' char[] writer2 = console.readPassword(); writer.append("PW: " + writer2); writer.flush(); } } }