I/O操作でデコレーションモードを使用(chjavachから)
1,java ioにおける装飾器の利用例
上のコードをよく見ると、一番奥の層はFileInputStreamオブジェクトで、それをBufferedInputStreamオブジェクトに渡し、BufferedInputStream処理後、処理後のオブジェクトをDataInputStreamオブジェクトに渡して処理します.FileInputStreamオブジェクトは元の装飾されたオブジェクトに相当し、BufferedInputStreamオブジェクトとDataInputStreamオブジェクトは装飾器に相当します.
2,自分で実現したI/Oストリームのデコレーション
机能を简単にして、英语を暗号化して保存することを実现しましょう.暗号化アルゴリズムとは言えません.英语のアルファベットを后に2つの位置に移动します.例えば、aがcになって、bがdになって、このようにして、最后のyがaになって、zがbになって、しかも简単のために、小文字だけを処理して、简単でしょう.
試験手順:
生成されたMyEncrypt.txtファイルの内容:cdefzab
上記の手順では、装飾器の順序が次のように変更されます.
//ストリーミング出力ファイル
このとき出力されたファイルは真っ白で、何もありませんでした.これはどこが問題になったのですか.
(1)成功した出力ストリームの内容の書き方の実行手順を見てみましょう.
•「dout.write("abcdxyz".getBytes();」という文を実行すると、DataOutputStreamのwriteメソッドが呼び出され、BufferedOutputStreamにデータが出力されます.
•BufferedOutputStreamストリームはキャッシュ付きストリームであるため、デフォルトのキャッシュ8192 byte、つまりデフォルトのストリームのキャッシュデータが8192 byteに達した場合、キャッシュ内のデータが自動的に出力されます.
•現在出力されるバイトは8192 byte未満であるため、自動的に出力されずにBufferedOutputStreamストリームにデータがキャッシュされます.
•「dout.close();」という文を実行すると、DataOutputStreamを閉じるように呼び出されます.これは、DataOutputStreamに入力されたストリームのcloseメソッド、すなわちBufferedOutputStreamのcloseメソッドに移行し、BufferedOutputStreamのcloseメソッドはFilterOutputStreamから継承され、FilterOutputStreamのcloseメソッド実装では、出力ストリームのメソッドflushが呼び出され、ストリームが閉じます.つまり、BufferedOutputStreamストリームにキャッシュされたデータが強制的に出力されます.
•BufferedOutputStreamストリームにキャッシュされたデータは、EncryptOutputStreamストリーム、つまり私たち自身が実現したストリームに強制的に出力され、キャッシュされず、処理された後も出力され続けます.
•EncryptOutputStreamストリームはFileOutputStreamにデータを出力し、FileOutputStreamは直接ファイルにデータを出力するので、この実装ではファイルの内容を出力します.
(2)ストリーム内の内容を出力できない書き方の実行手順を見てみる.
•「dout.write("abcdxyz".getBytes();」という文を実行すると、DataOutputStreamのwriteメソッドが呼び出され、EncryptOutputStreamにデータが出力されます.
•EncryptOutputStreamストリーム、つまり私たち自身が実現したストリームは、キャッシュされず、処理後も出力を続け、BufferedOutputStreamにデータを出力します.
•BufferedOutputStreamストリームはキャッシュ付きストリームであるため、デフォルトのキャッシュ8192 byte、つまりデフォルトのストリームのキャッシュデータが8192 byteに達した場合、キャッシュ内のデータが自動的に出力されます.
•現在出力されるバイトは8192 byte未満であるため、自動的に出力されずにBufferedOutputStreamストリームにデータがキャッシュされます.
•「dout.close();」という文を実行すると、DataOutputStreamを閉じるように呼び出されます.これは、DataOutputStreamストリームに流れるcloseメソッド、つまりEncryptOutputStreamのcloseメソッドに移行します.一方、EncryptOutputStreamのcloseメソッドはOutputStreamから継承され、OutputStreamのcloseメソッド実装では空のメソッドで、何もしていません.したがって,この実現方式はflushストリームのデータがなく,ファイルの内容も出力されず,当然空白である.
package decorationApp;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
//
public class IOTest {
public static void main(String[] args)throws Exception {
//
DataInputStream din = null;
try{
din = new DataInputStream(
new BufferedInputStream(
new FileInputStream("IOTest.txt") // , src ,
)
);
//
byte bs []= new byte[din.available()];
din.read(bs);
String content = new String(bs);
System.out.println(" ===="+content);
}finally{
if(din!=null)din.close();
}
}
}
上のコードをよく見ると、一番奥の層はFileInputStreamオブジェクトで、それをBufferedInputStreamオブジェクトに渡し、BufferedInputStream処理後、処理後のオブジェクトをDataInputStreamオブジェクトに渡して処理します.FileInputStreamオブジェクトは元の装飾されたオブジェクトに相当し、BufferedInputStreamオブジェクトとDataInputStreamオブジェクトは装飾器に相当します.
2,自分で実現したI/Oストリームのデコレーション
机能を简単にして、英语を暗号化して保存することを実现しましょう.暗号化アルゴリズムとは言えません.英语のアルファベットを后に2つの位置に移动します.例えば、aがcになって、bがdになって、このようにして、最后のyがaになって、zがbになって、しかも简単のために、小文字だけを処理して、简単でしょう.
package decorationApp;
import java.io.IOException;
import java.io.OutputStream;
/**
* , OutputStream
*/
public class EncryptOutputStream extends OutputStream{
//
private OutputStream os = null;
public EncryptOutputStream(OutputStream os){
this.os = os;
}
public void write(int a) throws IOException {
//
a = a+2;
//97 a
if(a >= (97+26)){
// , y z , 26 a b
a = a-26;
}
this.os.write(a);
}
}
試験手順:
package decorationApp;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
public class Client {
public static void main(String[] args) throws Exception {
//
DataOutputStream dout = new DataOutputStream(
new BufferedOutputStream(
//
new EncryptOutputStream(
new FileOutputStream("MyEncrypt.txt")))); // ,
//
dout.write("abcdxyz".getBytes()); //
dout.close();
}
}
生成されたMyEncrypt.txtファイルの内容:cdefzab
上記の手順では、装飾器の順序が次のように変更されます.
//ストリーミング出力ファイル
DataOutputStream dout = new DataOutputStream(
//
new EncryptOutputStream (
new BufferedOutputStream(
new FileOutputStream("MyEncrypt.txt"))));
このとき出力されたファイルは真っ白で、何もありませんでした.これはどこが問題になったのですか.
(1)成功した出力ストリームの内容の書き方の実行手順を見てみましょう.
•「dout.write("abcdxyz".getBytes();」という文を実行すると、DataOutputStreamのwriteメソッドが呼び出され、BufferedOutputStreamにデータが出力されます.
•BufferedOutputStreamストリームはキャッシュ付きストリームであるため、デフォルトのキャッシュ8192 byte、つまりデフォルトのストリームのキャッシュデータが8192 byteに達した場合、キャッシュ内のデータが自動的に出力されます.
•現在出力されるバイトは8192 byte未満であるため、自動的に出力されずにBufferedOutputStreamストリームにデータがキャッシュされます.
•「dout.close();」という文を実行すると、DataOutputStreamを閉じるように呼び出されます.これは、DataOutputStreamに入力されたストリームのcloseメソッド、すなわちBufferedOutputStreamのcloseメソッドに移行し、BufferedOutputStreamのcloseメソッドはFilterOutputStreamから継承され、FilterOutputStreamのcloseメソッド実装では、出力ストリームのメソッドflushが呼び出され、ストリームが閉じます.つまり、BufferedOutputStreamストリームにキャッシュされたデータが強制的に出力されます.
•BufferedOutputStreamストリームにキャッシュされたデータは、EncryptOutputStreamストリーム、つまり私たち自身が実現したストリームに強制的に出力され、キャッシュされず、処理された後も出力され続けます.
•EncryptOutputStreamストリームはFileOutputStreamにデータを出力し、FileOutputStreamは直接ファイルにデータを出力するので、この実装ではファイルの内容を出力します.
(2)ストリーム内の内容を出力できない書き方の実行手順を見てみる.
•「dout.write("abcdxyz".getBytes();」という文を実行すると、DataOutputStreamのwriteメソッドが呼び出され、EncryptOutputStreamにデータが出力されます.
•EncryptOutputStreamストリーム、つまり私たち自身が実現したストリームは、キャッシュされず、処理後も出力を続け、BufferedOutputStreamにデータを出力します.
•BufferedOutputStreamストリームはキャッシュ付きストリームであるため、デフォルトのキャッシュ8192 byte、つまりデフォルトのストリームのキャッシュデータが8192 byteに達した場合、キャッシュ内のデータが自動的に出力されます.
•現在出力されるバイトは8192 byte未満であるため、自動的に出力されずにBufferedOutputStreamストリームにデータがキャッシュされます.
•「dout.close();」という文を実行すると、DataOutputStreamを閉じるように呼び出されます.これは、DataOutputStreamストリームに流れるcloseメソッド、つまりEncryptOutputStreamのcloseメソッドに移行します.一方、EncryptOutputStreamのcloseメソッドはOutputStreamから継承され、OutputStreamのcloseメソッド実装では空のメソッドで、何もしていません.したがって,この実現方式はflushストリームのデータがなく,ファイルの内容も出力されず,当然空白である.