IO流 緩衝區、裝飾模式

字符流的緩衝區

對應類:

BufferedWriter

BufferedReader

緩衝區的出現是爲了提高流的操作效率,所以在創建緩衝區之前必須要先有流對象。將需要被提高效率的流對象作爲參數傳遞給緩衝區的構造函數。

關閉緩衝區,就是在關才緩衝區中的流對象。

newline():換行

FileWriter fw = FileWriter(“D:\\aa.txt”);

BufferedWriter bw = BufferedWriter(fw);

bw.write(“adfdsafdsa”);

bw.newline();

bw.write(“fdsafsda”);

bw.close();

 

BufferedReader

readLine():讀一行

FileReader fr = new FileReader(“d:\\txt.txt”);

BufferedReader br = new BufferedReader(fr);

String str=null;

while((str=br.readLine())!=null){

out.print(str);

}

br.close();

 

緩衝區的複製文件

BufferedWriter bw = null;

BufferedReader br = null;

 

try{

        bw = newBufferedWriter(new FileWriter(“D:\\aaa_copy.txt”));

        br = newBufferedReader(new FileReader(“D:\\aaa.txt”));

       

        String line = null;

        while((line=br.readLine())!=null){

               bw.write(line);

               bw.newLine();

               bw.flush();

}

}

 

自定義緩衝區類

class myBufferedReader{

        privater FileReaderr;

       

        myBufferedReader(FileReaderr){

               this.r = r;

}

 

public String myReadLine(){

       StringBuildersb = new StringBuilder();

       intch=0;

       while((ch=r.read())!=-1){

              if(ch==’\r’)

                     contine;

              if(ch==’\n’)

                     returnsb.toString();

              else

                     sb.append((char)ch);

}

if(sb.length()!=0)

       returnsb.toString();

return null;

}

 

public void myclose(){

       r.close();

}

}

 

裝飾設計模式:

當要對已有的對象進行功能增強時,可以定義類,將已有對象傳入,基於已有對象的功能,並提供加強功能。那麼自定義的該類就稱爲裝飾類。

 

裝飾類通常會通過構造方法接收被裝飾的對象,並基於被裝飾的對象的功能,提供更強的功能。

 

裝飾和繼承的區別:

例:

MyReader

        |--MyTextReader

        |--MyTextReader

變爲:

MyReader

        |--MyTextReader

        |--MyTextReader

        |--MyBuffereReader

裝飾模式比繼承要靈活,避免了繼承體系臃腫,而且降低了類與類之間的關係。裝飾類因爲增強已有對象,具備的功能和已有的是相同的,只不過提供了更強的功能。所有裝飾類和被裝飾類通常是都屬於一個體系中的。

import java.io.*;

class MyLineNumberReader{
 
 private FileReader fr;
 private int LineNumber=11;
 
 MyLineNumberReader(FileReader fr ){
  
  this.fr = fr;
 }
 
 public String myReadLine()throws Exception{
  
  StringBuffer sb = new StringBuffer();
  int ch;
  while((ch=fr.read())!=-1){
   
   if(ch=='\r'){
    continue;
   }
   if(ch=='\n'){
    LineNumber++; 
    return sb.toString();
   }
   else{
    sb.append((char)ch);
   }
  }
  
  if(sb.length()!=0){
   System.out.println("++++++++++++++++++++++++++++++++");
   return sb.toString();
  }
   
  return null;
 }
 
 public void setLineNumber(int LineNumber){
  
  this.LineNumber=LineNumber;
 }
 
 public int getLineNumber(){
  
  return LineNumber;
 }
 
 public void close()throws Exception{
  
  fr.close();
 }
}

class MyLineNumberDemo{
 
 public static void main(String[] args)throws Exception{
  
  FileReader fr = new FileReader("D:\\tmp\\aa_copy.txt");
  
  MyLineNumberReader lnr = new MyLineNumberReader(fr);
  
  lnr.setLineNumber(11);
  String str;
  while((str=lnr.myReadLine())!=null){
   
   System.out.println(lnr.getLineNumber()+":"+str);
  }
  
  lnr.close();
 }
}

 

LineNumberReader帶行號的裝飾類

getLineNumber();

setLineNumber();

 

自定義LineNumberReader

  FileReader fr = new FileReader("D:\\tmp\\aa_copy.txt");
  
  LineNumberReader lnr = new LineNumberReader(fr);
  
  lnr.setLineNumber(0);
  String str;
  while((str=lnr.readLine())!=null){
   
   System.out.println(lnr.getLineNumber()+":"+str);
  } 
  lnr.close();

 

 

字節流:

InputStream

OutputStream

 

FileInputStream

FileOutputStream

write(“abcd”.getBytes());//以單個字符存入

不需要用flush()方法刷新

 

FileInputStream fis = new FileInputStream(“aa.txt”);

byte[] buf = new byte[fis.available()];

fis.read(buf);

System.out.println(new String(buf));

fis.close();

不建議使用此方式,因爲考慮到文件比較大時,會發生內存溢出。

所以一般使用下面方式

 

FileInputStream fis = new FileInputStream(“aa.txt”);

byte[] buf = new byte[1024];

int num=0;

while((num=fis.read(buf))!=-1){

System.out.println(newString(buf,0,num));

}

 

複製一張圖片

    用字節讀取流對象和圖片關聯。

    用字節寫入流對象創建一個圖片文件。用於存儲獲取到的圖片數據。

    通過循環讀寫,完成數據的存儲。

    關才資源。

 

字節流的緩衝區

BufferedOutputStream

BufferedInputStream

 

BufferedInputStream bufis = new BufferedInputStream(newFileInputStream(“c:\\1.mp3”));

BufferedOntputStream bufos = new BufferedOntputStream(new FileOntputStream(“c:\\1_copy.mp3”));

int by=0;

while((by=bufis.read())!=-1){

        bufos.write(by);

}

 

七. 自定義字節流緩衝區

       import java.io.*;

      

       classMyBufferedInputStream{

              privateInputStream in;

              privatebyte[] buf = new byte[1024];

              private intpos=0,count=0;

              MyBufferedInputStream(InputStreamin){

                     this.in=in;

}

//一次讀一個字節,從緩衝區(字節數組)獲取。

publicint myRead(){

       //通過in對象讀取硬盤上數據,並存儲buf中。

       if(count==0){

              count = in.read(buf);

              if(count<0)

                     return -1;

              pos=0;

              byte b = buf[pos];

              count--;

              pos++;

              return b&255;

}elseif(count>0){

       byte b = buf[pos];

              count--;

              pos++;

              return b&255;

}

return-1;

}

publicvoid myClose(){

       in.close();

}

}

 

 

讀取鍵盤錄入

     System.out:對應的是標準輸出設備,控制檯

     System.in:對應的是鍵盤

 

InputStreamin = System.in;

int by =in.read();

System.out.println(by);

InputStreamin = System.in;

int ch=0;

while((ch=in.read())!=-1){

       System.out.println(by);

}

InputStreamin = System.in;

StringBuildersb = new StringBuilder();

while(true){

       int ch=in.read();

       if(ch==’\r’)

              contine;

       if(ch==’\n’){

              String s = sb.String();

              if(“over”.equals(s))

                     break;

              System.out.println(s.toUpperCase());

              sb.delete(0,sb.length());

}else{

       sb.appen((char)ch);

}

}

 

十一.              通過剛纔的鍵盤錄入一行數據並打印其大寫,發現其實就是讀一行數據的原理,也就是readLine方法。

       能不能直接使用readLine方法來完成鍵盤錄入的一行數據的讀取呢?

       readLine方法是BufferedReader類中的方法。

       而鍵盤錄入的read方法是字節流InputStream的方法。

       那麼將字節流轉換成字符流再使用字符流緩衝區的readLine的方法。

       InputStreamReader:將字節流轉換成字符流,在構造方法中傳入字節流。

       OutputStreamWriter

       code:

       //獲取鍵盤錄入對象。

       //InputStream in = System.in;

       //將字節流對象轉成字符流對象,使用轉換流:InputStreamReader;

       //InputStreamReader isr = newInputStreamReader(in);

       //爲了提高效率,將字符串進行緩衝區的高效操作,使用裝飾類:BufferedReader;

       //BufferedReader byfr = newBufferedReader(isr);

       BufferedReader byfr = newBufferedReader(new InputStreamReader(System.in));

      

       //OutputStream out = System.out;

       //OutputStreamWriter osw = newOutputStreamWriter(out);

       //BufferedWriter bufw = newBufferedWriter(osw);

       BufferedWriter bufw = newBufferedWriter(new OutputStreamWriter(System.out));

      

       String line=null;

       while((line=bufr.read())!=null){

                     if(“over”.equals(line))

                            break;

                     osw.write (line.toUpperCase());

                     bufw.newLine();

                     osw.flush();

}

byfr.close();

 

十二.             

1.     將鍵盤輸入的數據寫入到一個文件中,只需改上述代碼中的目的由控制檯改爲文件。

       BufferedWriter bufw= new BufferedWriter(new OutputStreamWriter(new FileOutputStream(“out.txt”)));

       2.     將一個文件的數據打印在控制檯上。

       BufferedReader bufr= new BufferedReader(new InputStreamReader(new FileInputStream(“copyPic.java”)));

      

       流操作的基本規律:

       流對象有很多,不知識該用哪一個。

       通過兩個明確來完成。

    明確源和目的。

     源:輸入流:InputStream      Reader

     目的:輸出流:OutputStream              Writer

    操作的數據是否是純文本。

     是:字符流:Reader              Writer

     不是:字節流:InputStream          OutputStream

    當體系明確後,在明確要使用哪個具體的對象。通過設備來進行區分:

     源設備:內存,硬盤,鍵盤

     目的設備:內存,硬盤,控制檯

 

       需求:

    將一個文本文件中的數據存儲到另一個文件中,複製文件。

源:InputStreamReader //因爲是源,所以使用讀取流,判斷是不是操作文本文件,是!則選擇Reader。這樣體系就明確了。

接下來明確要使用該體系中的哪個對象。明確設備:硬盤上的一個文件。

Reader體系中可以操作文件的對象是:FileReader

是否需要提高效率,是!則加入Reader體系中的緩衝區:BufferedReader;

 

目的:OutputStreamWriter //目的是否是純文本,是!則Writer。設備:硬盤上的一個文件。Writer體系中可以操作文件的對象是:FileWriter

是否需要提高效率,是!則加入Writer體系中的緩衝區:BufferedWriter;

 

    將鍵盤錄入的數據保存到一個文件中。

源:InputStream Reader //判斷是不是純文件?是!則用Reader

設備:鍵盤,對應的對象是System.in ??? 不是選擇Reader嗎?System.in對應的不是字節流嗎?爲了操作鍵盤 的文本數據方便。轉成字符流按照字符串操作是最方便的。所以既然明確了Reader,那麼就將System.in轉換成Reader

用到了Reader體系中的轉換流,InputStreamReader

code:

InputStreamReader isr = new InputStreamReader(System.in);

//需要提高效率嗎?需要!BufferedReader

BufferedReader bufr = new BufferedReader(isr);

 

目的:OutputStream Writer  //是否是純文本,是!則用Writer

設備:硬盤,一個文件,使用FileWriter

code:

FileWriter fw = new FileWriter(“a.txt”);

//提高效率?

BufferedWriter bufw = new BufferedWriter(fw);

 

擴展,想要把錄入的數據按照指定的編碼表存入,將數據存到文件中。

 

目的:OutputStream Writer  //是否是純文本,是!則用Writer

設備:硬盤,一個文件,使用FileWriter

但是FileWriter是使用的默認編碼表:GBK

 

但是存儲時,需要加入指定編碼表,而指定的編碼表只有轉換流可以指定。所以要使用的對象是OutputStreamWriter.而該轉換對象要接收一個字節輸出流,而且還可操作的文件的字節輸出流。FileOutputStream

code:

OutputStreamWriterosw = new OutputStreamWriter(new FileOutputStream(“d.txt”),”UTF-8”);

需要高效嗎?需要!

BufferedWriterbufw = new BuffereWriter(osw);

 

所以,記住!轉換流什麼使用,字符和字節之間的橋樑,通常,涉及到字符編碼轉換時,需要用到轉換流。

 

讀取指定編碼表的文件

InputStreamReader

 

十三.       改變標準輸入輸出設備-不常用

       System.setIn(new FileInputStream(“a.txt”);

       System.setOut(newFileOutputStream(“b.txt”));

 

十四.       系統日誌文件

       catch(Exception e){

              Date d = newDate();

              SimpleDateFormatsdf = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);

              String s =sdf.format(d);

 

              PrintStreamps = new PrintStream(“exeception.log”)

              ps.println(s);

              System.setOut(ps);

              e.printStackTreace(System.out);

}

 

十四.       打印系統信息

       Properties p =System.getProperties();

       //p.list(System.out);

       p.liset(newPrintStream(“systeminfo.txt”));

 

發佈了67 篇原創文章 · 獲贊 8 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章