1. 程式人生 > 其它 >1輸入輸出流

1輸入輸出流

技術標籤:java

過濾流

public class FilterInputStream extends InputStream { //典型的裝飾模式
protected volatile InputStream in; //被裝飾目標
protected FilterInputStream(InputStream in) { //通過構造器組裝被裝飾物件
this.in = in;
}
public int read() throws IOException {//呼叫Filter中的read方法時實際操作是由被裝飾物件實現return in.read();
}
}

所謂的過濾流實際上就是類似上面的加密處理,在輸入之後(後置處理,被裝飾物件先執行)或者輸出之前(前置

處理,先處理然後被裝飾物件執行)進行一下額外的處理,最終實際操作是呼叫被裝飾物件的方法完成工作,依靠
這種裝飾模式實現在節點流的基礎上附加額外功能.當然也允許多個過濾流巢狀從而達到功能累加的目的

寫出資料自定義過濾流SecurityWriter(FilterWriter)
public class SecurityWriter extends FilterWriter {
protected SecurityWriter(Writer out) {
super(out);
}
public void write(int c) throws IOException {
if (c >= 'a'
&& c <= 'z') { c = (c - 'a' + 13) % 26 + 'a'; } else if (c >= 'A' && c <= 'Z') { c = (c - 'A' + 13) % 26 + 'A'; } super.write(c); } }
public class SecurityReader extends FilterReader {
protected SecurityReader(Reader in) {
super(in);
}
public int read() throws IOException {
int c = super.read(); if (c >= 'a' && c <= 'z') { c = (c - 'a' + 13) % 26 + 'a'; } else if (c >= 'A' && c <= 'Z') { c = (c - 'A' + 13) % 26 + 'A'; } return c; } }

橋接轉換流
InputStreamReader和OutputStreamWriter提供了位元組流和字元流之間的橋接轉換功能,用於與位元組資料到字元
資料之間的轉換,無需程式設計實現將位元組拼接為字元
轉換流可以在構造時指定其編碼字符集
InputStreamReader用於將一個InputStream型別的輸入流自動轉換為Reader字元流
OutputStreamWriter用於將一個Writer字元輸出流轉換為OutputStream位元組輸出流
InputStreamReader構造器
InputStreamReader(InputStream)
InputStreamReader(InputStream, String)
InputStreamReader(InputStream, Charset)
InputStreamReader(InputStream, CharsetDecorder)

Reader r=new InputStreamReader(System.in);
int kk=r.read(); //例如輸入的是“中國”,這裡實際讀取的是"中"
//因為這裡讀取的是一個位元組,所以輸入"中國",實際讀取的是"中"的一個位元組,輸出顯示為?
kk=System.in.read();
System.out.println("輸入的是:"+(char)kk);

InputSteram is=new InputStreamReader(System.in,”iso8859-1”);

Reader r=new InputStreamReader(System.in, "gbk");
int kk=r.read(); //例如輸入的是"中國",實際讀取的是"中"
System.out.println("輸入的是:"+(char)kk);

緩衝流是套接在響應的節點流之上,對續寫的資料提供緩衝的功能,提高讀寫的效率,同時增加了一些新方法
以介質是硬碟為例,位元組流和字元流的弊端:在每一次讀寫的時候,都會訪問硬碟。 如果讀寫的頻率比較高的時
候,其效能表現不佳。為了解決以上弊端,採用快取流。
快取流在讀取的時候,會一次性讀較多的資料到快取中,以後每一次的讀取,都是在快取中訪問,直到快取中的數
據讀取完畢,再到硬碟中讀取。

BueredReader(Reader)不定義快取大小,預設8192
BueredReader(Reader in, int size)size為自定義緩衝區的大小
BueredWriter(Writer)
BueredWriter(Writer out, int size)size為自定義緩衝區的大小
BueredInputStream(InputStream)
BueredInputStream(InputStream in, int size)size為自定義緩衝區的大小
BueredOutputStream(OutputStream)
BueredOutputStream(OuputStream out, int size)size為自定義緩衝區的大小

緩衝輸入流的方法

BuedReader提供了一個方法readLine():String,但是BueredInputStream中並沒有這個
BueredReader提供了readLine方法用於讀取一行字串,以\r或\n分割(換行符)
如果讀取內容為null,則表示讀取到了流的末尾
readLine方法會自動剔除本行內容末尾的換行符
BueredWriter提供了newLine方法用於寫入一個行分隔符
對於輸出的緩衝流,寫入的資料會先在記憶體中快取,使用ush方法會使記憶體中的資料立即寫出

鍵盤錄入


```java
System.in:InputStream用於指代系統預設的輸入裝置—鍵盤
方法read():int 可以實現程式碼執行到這裡則會阻塞等待,只要輸入資料為止
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.println("輸入資料");
String temp="";
while((temp=br.readLine()).trim().length()>0){
if("quit".equals(temp)) break;
System.out.println(temp);
}
br.close();
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
bw.write("只有緩衝區滿才自動進行輸出顯示");
bw.flush(); //重新整理緩衝區,否則看不到輸出內容
System.in.read();
bw.close(); //關閉輸出時會首先自動進行重新整理緩衝區

DataInputStram和DataOutputStream分別繼承自InputStream和OuputStream,屬於過濾流,需要分別套接在
InputStream和OutputStream型別的節點流上
只有位元組流,沒有對應的字元流
DataInputStream和DataOutputStream提供了可以存取與機器無關的Java原始型別資料的方法
DataInputSteram和DataOutputStream構造方法為
DataInputStream(InputStream)
DataOutputStream(OutputStream)
讀取、寫出一個double資料到檔案中


```java
//使用資料流就可以直接操作簡單型別資料
double dd=123.4567;
FileOutputStream fos=new FileOutputStream("d:\\a.data");
fos.write((dd+"").getBytes());
fos.close();
//如果不使用資料流,則需要額外編碼進行資料型別轉換
FileInputStream fis=new FileInputStream("d:/a.data");
byte[] buffer=new byte[8192];
int len=fis.read(buffer);
fis.close();
String str=new String(buffer,0,len);
double dd=Double.parseDouble(str);
System.out.println(dd);

加入需要寫一個double,然後一個String,然後再一個int
需要將輸入內容轉換為String,並且為了區分資料需要引入特殊符號,例如@@,輸入資料為[email protected]@shi ya
[email protected]@12。從功能角度上說沒問題,但是編碼太複雜了,所以引入Data型別的輸入輸出流
//這裡不使用OutputStream定義變數的原因是:需要使用DataOutputStream中定義的特殊方法,而不是父類中
定義的通用方法

DataOutputStream dos=new DataOutputStream(new FileOutputStream("d:\\a.data"));
dos.writeDouble(123.456);
dos.writeChars("趙天愛小猴!");
dos.writeInt(12);
dos.close();

由於讀取出現問題,針對中間的String資料引入一個額外的資料,其中儲存String的char個數
寫出資料

double salary=123.456;
String ss="趙天愛小猴,小猿愛小主,小胡招小天";
int age=12;
DataOutputStream dos=new DataOutputStream(new BufferedOutputStream(new
FileOutputStream("d:\\aa.data")));
dos.writeDouble(salary);
dos.writeInt(ss.length());
dos.writeChars(ss);
dos.writeInt(age);
dos.close();

讀取資料

double salary=0;
String str="";
int age=0;
//讀取資料的前提是必須知道資料的結構
DataInputStream dis=new DataInputStream(new BufferedInputStream(new
FileInputStream("d:\\aa.data")));
salary=dis.readDouble();
StringBuilder sb=new StringBuilder();
int len=dis.readInt();
for(int i=0;i<len;i++) sb.append(dis.readChar());
str=sb.toString();
age=dis.readInt();
System.out.println(salary+"---"+str+"---"+age);

注意:讀取資料判斷檔案結束EOFException,這裡沒有-1
在具體應用中建議針對字串使用readUTF和writeUTF

DataOutputStream dos=new DataOutputStream(new FileOutputStream("data2.txt"));
dos.writeDouble(1234.56);
String str="猴子愛小終,小終愛信心";
dos.writeUTF(str);
dos.writeInt(99);
dos.close();
DataInputStream dis = new DataInputStream(new FileInputStream("data2.txt"));
double d1 = dis.readDouble();
String ss=dis.readUTF();
int kk = dis.readInt();
System.out.println(d1 + "\t" + ss + "\t" + kk);
dis.close();