IO學習(二)

------- android培訓java培訓、期待與您交流! ----------

字符流的緩衝區

     1、緩衝區的出現提高了對數據的讀寫效率。

      2、對應類:BufferedWriter              BufferedReader

      3、緩衝區要結合流纔可以使用。

      4、在流的基礎上對流的功能進行了增強。

/*字符流的緩衝區
緩衝區的出現是爲了提高流的操作效率而出現的。所以在創建緩衝區之前,必須要先有流對象。
該緩衝區中提供了一個跨平臺的換行符。newLine();

*/

import  java.IO.*;
class  BufferedWriterDemo
{
 public static void main(String[] args)throws IOException 
 {
  //創建一個字符寫入流對象
  FileWriter fw=new FileWriter("buf.txt");
  //爲了提高字符寫入流效率。加入緩衝技術。
  //只要將需要被提高效率的流對象作爲參數傳遞給緩衝區的構造函數即可。
  BufferedWriter bufw=new BufferedWriter(fw);
  for(int x=1;x<5;x++)
   {
  bufw.write("abcd"+x);
  bufw.newLine();
  bufw.flush();
  }
  //記住,只要用到緩衝區,就要記得刷新。
  //bufw.flush();
  //其實關閉緩衝區,就是在關閉緩衝區中的流對象
  bufw.close();
 }
}



/*字符讀取流緩衝區
該緩衝區提供了一個一次讀一行的方法readLine,方便於對文本數據的獲取
當返回null時,表示獨到文件末尾。
readLine方法返回的時候只返回回車符之前的數據內容。並不返回回車符。

*/

import  java.IO.*;
class  BufferedReaderDemo
{
 public static void main(String[] args) 
 {
  //創建一個讀取流對象和文件相關聯。
  FileReader fr=new FileReader("demo.txt");
  //爲了提高效率。加入緩衝技術。將字符讀取流對象作爲參數傳遞給緩衝對象的構造函數。
         BufferedReader bufr=new BufferedReader(fr);

  String line=null;
  while((line=bufr.readLine())!=null)
   {
      System.out.println(line);
  }
  bufr.close();
 }
}


/*
通過緩衝區複製一個.java文件
*/

import  java.IO.*;
class  CopyTextByBuf
{
 public static void main(String[] args) 
 {
  BufferedReader bufr=null;
  BufferedWriter bufw=null;
  try{
  bufr=new BufferedReader(new FileReader("demo.txt"));
  bufw=new BufferedWriter(new FileWriter("demo_copy.txt"));
  String line=null;
  while((line=bufr.readLine)!=null){
   bufw.write(line);
   bufw.newLine();
   bufw.flush();
  }
  }catch(IOException e){
  throw new RuntimeException("讀寫失敗!");
  }finally{
  try{
  if(bufr!=null)
   bufr.close();
  }catch(IOException e){
  throw new RuntimeException("讀取關閉失敗!");
  }
  try{
  if(bufw!=null)
   bufw.close();
  }
  catch(IOException e){
  throw new RuntimeException("寫入關閉失敗!");
  }
  }
 }
}


readLine方法的原理:無論是讀一行,或者讀取多個字符。其實最終都是在硬盤上一個一個讀取。所以最終使用的還是

read方法一次讀一個的方法。

 

模擬緩衝區的特點:

/*
明白了BufferedReader類中特有方法readLine的原理後,可以自定義一個類中包含一個功能和
readLine一致的方法。來模擬一下BufferedReader
*/

import java.IO.*;

class MyBufferedReader{
 private FileReader r;
 MyBufferedReader(FileReader r){
 this.r=r;
 }
 //可以一次讀一行數據的方法
 public String myReadLine()throws IOException {
  //定義一個臨時容器。原BufferedReader封裝的是字符數組。
  //爲了演示方便。定義一個StringBuilder容器。因爲最終還是要講數據變成字符串。
  StringBuilder sb=new StringBuilder();
  int ch=0;
  while((ch=r.read())!=-1){
  if(ch=='\r')
   continue;
  if(ch=='\n')
   return sb.toString();
  else
   sb.append((char)ch);
  }
  if(sb.length()!=0)
   return sb.toString();
  return null;
 }
 public void myClose()throws IOException
  {
         r.close();
     }
 }

class  MyBufferedReaderDemo
{
 public static void main(String[] args) 
 {
  FileReader fr=new FileReader("buf.txt");

 MyBufferedReader myBuf=new MyBufferedReader(fr);
 String line=null;
 while((line=myBuf.myReadLine())!=null){
 System.out.printlm(line);
 }
 myBuf.myClose();
 } 
}


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

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

裝飾模式比繼承要靈活,避免了繼承體系的臃腫,而且降低了類與類之間的關係。

 

裝飾類因爲增強已有對象,具備的功能和已有的是相同的,只不過提供了更強功能

所以裝飾類和被裝飾類通常都是屬於一個體系的。

 

字符流:FileReader    FileWriter    BufferedReader      BufferedWriter

字節流:InputStream(讀)      OutputStream(寫)

import java.IO.*;
class  FileStream
{
 public static void main(String[] args) 
 {
  writeFile();
 }
 public static void readFile()_3
  {
        FileInputStream fis=new FileInputStream("fos.txt");
    /* //available()獲取的是字節的個數。
     int num=fis.available();
      System.out.println("num"+num);
     */
     byte[] buf=new byte[fis.available()];//定義一個剛剛好緩衝區。不用再循環了
     fis.read(buf);

     System.out.println(new String(buf));
     fis.close();
     }
public static void readFile()_2
   {
          FileInputStream fis=new FileInputStream("fos.txt");
     byte[] buf=new byte[1024];
     int len=0;
     while((len=fis.read(buf))!=-1)
      {
     System.out.println(new String(buf,0,len));
     }
     fis.close();
       }
 public static void readFile()_1
  {
         FileInputStream fis=new FileInputStream("fos.txt");
   int ch=0;
   while((ch=fis.read())!=-1)
    {
   System.out.println("ch="+(char)ch);
   }
   fis.close();
      }
 public static void writeFile()
  {
 FileOutputStream fos=new FileOutputStream("fos.txt");
 fos.write("abcd".getBytes());
 //關閉流資源必須寫
 fos.close();
 }
} 

/*
複製一個圖片

思路:
1、用字節獲取流對象和圖片關聯
2、用字節寫入流對象創建一個圖片文件。用於存儲獲取到的圖片數據。
3、通過循環讀寫,完成數據的存儲。
4、關閉流資源
*/

import java.IO.*;

class  CopyPic
{
 public static void main(String[] args) 
 {
  FileOutputStream  fos=null;
  FileInputStream fis=null;
         try
         {
   fos=new FileOutputStream("c:\\2.bmp");
   fis=new FileInputStream("C:\\1.bmp");
            byte[]buf=new byte[1024];
   int len=0;
   while((len=fis.read(buf))!=-1){
   fos.write(buf,0,len);
   }
         }
         catch (IOException e)
         {
    throw new RuntimeException("複製文件失敗");
         }finally{
   try
   {
    if(fis!=null)
       fis.close();
   }
   catch (IOException e)
   {
    throw new RuntimeException("讀取關閉失敗");
   }

         try
   {
    if(fos!=null)
       fos.close();
   }
   catch (IOException e)
   {
    throw new RuntimeException("讀取關閉失敗");
   }

   }
 }
}


/*

字符流:FileReader    FileWriter     BufferedReader      BufferedWriter

字節流:FileInputStream     FileOutputStream      BufferedInputStream      BufferedOutputStream 

*/

/*
讀取鍵盤錄入
System.out:對應的是標準的輸出設備,控進臺。
System.in:對應的標準輸入設備:鍵盤。
需求:
通過鍵盤錄入數據。
當錄入一行數據後,就將改行數據進行打印。
如果錄入的數據是over ,那麼停止錄入。

*/

import java.IO.*;
class  ReadIn 
{
 public static void main(String[] args) 
 {
  InputStream in=System.in;
  StringBuilder sb=new StringBuilder();
  while(true)
   {
          int ch=in.read();
    if(ch=='\r')
     continue;
    if(ch=='\n')
     {
            String s=sb.toString();
      if("over".equals(s))
       break;
      System.out.println(s.toUpperCase());
      sb.delete(0,sb.length());
         }
      else
       sb.append((char)ch);
      }
 }
}

/*

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

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

readLine方法是字符流BuffeedReader類中的方法。

而鍵盤錄入的read方法是字節流InputStreamReader的方法。那麼能不能講字節流轉成字符流在使用字符流緩衝區的readLine方法呢?

*/

import jav.IO.*;
class  transStreamDemo
{
 public static void main(String[] args) 
 {
  //獲取鍵盤錄入對象。
  InputStreamReader in=System.in;
  //將字節流對象轉成字符流對象,使用轉換流。InputStreamReader
         InputStream isr =new InputStreamReader(in);
   //爲了提高效率,將字符串進行緩衝區高效操作。使用BufferedReader
   BufferedReader bufr=new BuffferedReader(isr);
   String line=null;
   while((line=bufr.readLine())!=null)
    {
   if("over".equals(line))
             break;
   System.out.println(line.toUpperCase());
   }
   bufr.close();
 }
}

InputStreamReader是字節通向字符的橋樑。

OutputStreamWriter是字符通向字節的橋樑。

import jav.IO.*;
class  transStreamDemo
{
 public static void main(String[] args) 
 {
  //獲取鍵盤錄入對象。
  //InputStreamReader in=System.in;
  //將字節流對象轉成字符流對象,使用轉換流。InputStreamReader
         //InputStream isr =new InputStreamReader(in);
   //爲了提高效率,將字符串進行緩衝區高效操作。使用BufferedReader
   //BufferedReader bufr=new BuffferedReader(isr);
   //鍵盤錄入的最常見寫法。
              BufferedReader  bufr=new BufferedReader(new InputStreamReader(System.in));

 

        // OutputStream out=System.out;
   //OutputStreamWriter osw=new OutputStreamWriter(out);
         //BufferedReader bufw=new BufferedRader(osw);
              BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(System.out));

   String line=null;
   while((line=bufr.readLine())!=null)
    {
   if("over".equals(line))
             break;
   //System.out.println(line.toUpperCase());
   osw.write(line.toUpperCase());
   osw.flush();
   }
   bufr.close();
 }
}

流操作的基本規律:最痛苦的就是流對象有很多不知道該用哪一個。

通過三個明確來完成。

1、明確源和目的。源:輸入流。InputStream    Reader

目的:輸出流:OutputStream    Writer

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

是:字符流         不是:字節流

3、檔體系明確後在明確要使用那個具體的對象。通過設備來進行區分:源設備:內存硬盤。鍵盤

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

需求1、將一個文件中的數據存儲到另一個文件中。複製文件。

           源:因爲是源,所以要使用讀取流。InputStream   Reader 

是不是操作文本文件。是!這是就可以選擇Reader這樣體系就明確了。

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

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

 

是否需要提高效率?是!加入Reader體系中緩衝區BufferedReader.

FileReader  fr=new FileReader("a.txt");

BufferedReader  bufr=new BufferedReader(fr);

 

目的:OutputStream    Writer  是否是純文本?是!Writer

設備:硬盤上一個文件。

Writer體系中可以操作文件的對象FileWriter。

是否提高效率:是!加入Writer體系中緩衝區BufferedWriter

FileWriter  fw=new FileWriter("b.txt");

BufferedWriter  bufw=new BufferedWriter(fw);

 需求2、將鍵盤錄入的數據保存到一個文件中,這個需求中有源和目的都存在,那麼分別分析

源:InputStream    Reader 是不是純文本?是!Reader

設備:鍵盤,對應的對象是System.in 不是選擇Reader嗎?System.in對應的不是字節流嗎?爲了操作鍵盤的文本數據方便,

轉換成字符流按照字符串操作是最方便的。所以既然明確了Reader,那麼就將System.in轉換成Reader,用了

Reader體系中轉換流InputStreamReader

InputStreamReader  isr=new InputStreamRader(isr);

 

目的:OutputStream   Writer

是否是純文本?是!Writer

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

FileWriter  fw=new FileWriter ("c.txt");

需要提高效率嗎?需要

BufferedWriter    bufw=new BufferedWriter(fw);

************************************************************

擴展一下想要把錄入的數據按照指定的編碼表(UTF-8),將數據存到文件中。

目的:OutputStream   Writer

是否是純文本?是!Writer。

設備:硬盤上的一個文件使用FileWriter但是FileWriter是使用的默認編碼表。GBK

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

OutputStreamWriter  osw   =new OutputStreamWriter(osw);

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

class  TransStreamDemo2
{
 public static void main(String[] args)
 {
 //鍵盤的最常見寫法
 BufferedReader bufr=new BufferedWriter(new InputStreamReader(System.in));
 BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("d2.txt"),"UTF-8"));
 String line=null;
 while((line=bufr.readLine())!=null)
  {
   if("over".equals(line))
    break;
    bufw.write(line.toUpperCase());
    bufw.newLine();
    bufw.flush();
 }
 bufr.close();
 }
}
------- android培訓java培訓、期待與您交流! ----------

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章