1.1、字符流的緩沖區
緩沖區的出現是為了提高IO的讀寫效率
對應類
BufferedReader
BufferedWriter
緩沖區要結合流才可以使用
在流的基礎上對流的功能進行了增強
1.2、BufferedReader、BufferedWriter
public class BufferedWriterextends Writer
構造方法摘要 | |
---|---|
BufferedWriter(Writer out) 創建一個使用默認大小輸出緩沖區的緩沖字符輸出流。 | |
BufferedWriter(Writer out, int sz) 創建一個使用給定大小輸出緩沖區的新緩沖字符輸出流。 |
將文本寫入字符輸出流,緩沖各個字符,從而提供單個字符、數組和字符串的高效寫入。
可以指定緩沖區的大小,或者接受默認的大小。在大多數情況下,默認值就足夠大了。
該類提供了 newLine() 方法,它使用平臺自己的行分隔符概念,此概念由系統屬性 line.separator 定義。并非所有平臺都使用新行符 ('/n') 來終止各行。因此調用此方法來終止每個輸出行要優于直接寫入新行符。
通常 Writer 將其輸出立即發送到底層字符或字節流。除非要求提示輸出,否則建議用 BufferedWriter 包裝所有其 write() 操作可能開銷很高的 Writer(如 FileWriters 和 OutputStreamWriters)。例如,
PRintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));
將緩沖 PrintWriter 對文件的輸出。如果沒有緩沖,則每次調用 print() 方法會導致將字符轉換為字節,然后立即寫入到文件,而這是極其低效的。
public class BufferedReaderextends Reader
構造方法摘要 | |
---|---|
BufferedReader(Reader in) 創建一個使用默認大小輸入緩沖區的緩沖字符輸入流。 | |
BufferedReader(Reader in, int sz) 創建一個使用指定大小輸入緩沖區的緩沖字符輸入流。 |
從字符輸入流中讀取文本,緩沖各個字符,從而實現字符、數組和行的高效讀取。
可以指定緩沖區的大小,或者可使用默認的大小。大多數情況下,默認值就足夠大了。
通常,Reader 所作的每個讀取請求都會導致對底層字符或字節流進行相應的讀取請求。因此,建議用 BufferedReader 包裝所有其 read() 操作可能開銷很高的 Reader(如 FileReader 和 InputStreamReader)。例如,
BufferedReader in = new BufferedReader(new FileReader("foo.in"));
將緩沖指定文件的輸入。如果沒有緩沖,則每次調用 read() 或 readLine() 都會導致從文件中讀取字節,并將其轉換為字符后返回,而這是極其低效的。
通過用合適的 BufferedReader 替代每個 DataInputStream,可以對將 DataInputStream 用于文字輸入的程序進行本地化
1.3、示例
在創建緩沖區之前,必須先有流對象
package com.pb.io.demo2;/**創建緩沖區之間必須,先創建流使用緩沖區,要flush,刷新*//**創建緩沖區之間必須,先創建流使用緩沖區,要flush,刷新*/import java.io.*;class BufferedReaderAndWriterDemo1 { public static void main(String[] args) { File source=new File("d://demo.txt"); File objFile=new File("d://a.txt"); useBuffered(source,objFile); } public static void useBuffered(File source,File objFile){ BufferedReader br=null; BufferedWriter bw=null; try{ //聲明緩沖區對象,并將字符流做為參數傳入 br=new BufferedReader(new FileReader(source)); bw=new BufferedWriter(new FileWriter(objFile)); //接收讀取的長度 String line=null; //讀取內容并放入buf中,判斷是不是最后 while((line=br.readLine())!=null){ //寫入,有多長寫多長 bw.write(line,0,line.length()); bw.newLine(); } System.out.println("讀寫完成!"); }catch(IOException e){ System.out.println(e.toString()); }finally{ try{ if(bw!=null) bw.flush(); bw.close(); }catch(IOException e){ System.out.println(e.toString()); } try{ if(br!=null) br.close(); }catch(IOException e){ System.out.println(e.toString()); } } }}
2.1、示例
package com.pb.io.demo2;import java.io.File;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;public class MyBuffered { private FileReader fr; public MyBuffered(FileReader fr) { this.fr = fr; } /* * 可以一次讀一行的方法 */ public String myReadLine() throws IOException { // 定義一個臨時 容器,原BufferedReader封裝的是字符數組 // 為了方便,定義一個StringBuilder StringBuilder sb = new StringBuilder(); int ch = 0; while ((ch = fr.read()) != -1) { if (ch == '/r') { continue; } if (ch == '/n') { return sb.toString(); } // 讀一個存一個 sb.append((char)ch); } if(sb.length()!=0){ return sb.toString(); } return null; } public void myClose() throws IOException{ if (fr != null) fr.close(); } public static void main(String[] args) throws IOException { File file=new File("d://demo.txt"); MyBuffered mb=new MyBuffered(new FileReader(file)); String line=null; while((line=mb.myReadLine())!=null){ System.out.println(line); } mb.myClose(); }}
3.1、裝飾設計模式
裝飾設計模式:
當想要對已經有的對象進行功能增強時,
可以定義類,將已經對象傳入,基于已經有的功能,并提供加強功能。
那么自定義的該類就稱為裝飾類
package com.pb.io.demo3;class Person{ public void eat(){ System.out.println("吃飯"); }}class SuperPerson{ private Person p; public SuperPerson(Person p) { super(); this.p = p; } public void superEat(){ System.out.println("開胃酒"); p.eat(); System.out.println("甜點"); System.out.println("來一根"); }}public class PersonTest { public static void main(String[] args) { Person p=new Person(); p.eat(); SuperPerson sp=new SuperPerson(p); sp.superEat(); }}
3.2、與繼承之間的關系
裝飾類通常會通過構造方法接收被被裝飾的對象,并基于被裝飾的對象的功能,提供更強的功能
裝飾模式比繼承靈活,避免了繼承體系臃腫
而且降低了類于類之間的關系
裝飾類因為增強已有對象,具備的功能和已經的是相同的,只不過提供了更強的功能。
所以裝飾類和被裝飾類通常是都屬于一個體系中。
4.1、
構造方法摘要 | |
---|---|
LineNumberReader(Reader in) 使用默認輸入緩沖區的大小創建新的行編號 reader。 | |
LineNumberReader(Reader in, int sz) 創建新的行編號 reader,將字符讀入給定大小的緩沖區。 |
方法摘要 | |
---|---|
int | getLineNumber() 獲得當前行號。 |
void | mark(int readAheadLimit) 標記該流中的當前位置。 |
int | read() 讀取單個字符。 |
int | read(char[] cbuf, int off, int len) 將字符讀入數組中的某一部分。 |
String | readLine() 讀取文本行。 |
void | reset() 將該流重新設置為最新的標記。 |
void | setLineNumber(int lineNumber) 設置當前行號。 |
long | skip(long n) 跳過字符。 |
4.2、示例
package com.pb.io.demo4;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;import java.io.LineNumberReader;public class LineNumberReaderDemo { public static void main(String[] args) { LineNumberReader lnr=null; try { lnr=new LineNumberReader(new FileReader("d://demo.txt")); //設置開始行叼 lnr.setLineNumber(100); String line=null; while((line=lnr.readLine())!=null){ //getLineNumber默認從1開始,設置后從設置的行號開始 System.out.println(lnr.getLineNumber()+":"+line); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ try { if(lnr!=null) lnr.close(); } catch (IOException e) { e.printStackTrace(); } } }}
4.3、自定義
package com.pb.io.demo4;import java.io.File;import java.io.FileReader;import java.io.IOException;import java.io.Reader;public class MyLineNumberReader { private Reader reader; private int lineNumber; public MyLineNumberReader(Reader reader) { this.reader = reader; } /* * 讀一行 */ public String myReadLine() throws IOException { lineNumber++; StringBuilder sb = new StringBuilder(); int ch=0; while ((ch = reader.read()) != -1) { if (ch == '/r') continue; if (ch == '/n') return sb.toString(); sb.append((char) ch); } if (sb.length() != 0) return sb.toString(); return null; } public void myClose() throws IOException{ reader.close(); } public Reader getReader() { return reader; } public void setReader(Reader reader) { this.reader = reader; } public int getLineNumber() { return lineNumber; } public void setLineNumber(int lineNumber) { this.lineNumber = lineNumber; } public static void main(String[] args) throws IOException { File file=new File("d://demo.txt"); MyLineNumberReader mln=new MyLineNumberReader(new FileReader(file)); String line=null; //mln.setLineNumber(100); while((line=mln.myReadLine())!=null){ System.out.println(mln.getLineNumber()+":"+line); } mln.myClose(); }}
5.1、字節流
OutputStream寫、InputStream讀
FileOutputStream、FileInputStream 字節流輸出、輸入流
構造方法摘要 | |
---|---|
OutputStream() |
方法摘要 | |
---|---|
void | close() 關閉此輸出流并釋放與此流有關的所有系統資源。 |
void | flush() 刷新此輸出流并強制寫出所有緩沖的輸出字節。 |
void | write(byte[] b) 將 b.length 個字節從指定的 byte 數組寫入此輸出流。 |
void | write(byte[] b, int off, int len) 將指定 byte 數組中從偏移量 off 開始的 len 個字節寫入此輸出流。 |
abstract void | write(int b) 將指定的字節寫入此輸出流。 |
構造方法摘要 | |
---|---|
InputStream() |
方法摘要 | |
---|---|
int | available() 返回此輸入流下一個方法調用可以不受阻塞地從此輸入流讀取(或跳過)的估計字節數。 |
void | close() 關閉此輸入流并釋放與該流關聯的所有系統資源。 |
void | mark(int readlimit) 在此輸入流中標記當前的位置。 |
boolean | markSupported() 測試此輸入流是否支持 mark 和 reset 方法。 |
abstract int | read() 從輸入流中讀取數據的下一個字節。 |
int | read(byte[] b) 從輸入流中讀取一定數量的字節,并將其存儲在緩沖區數組 b 中。 |
int | read(byte[] b, int off, int len) 將輸入流中最多 len 個數據字節讀入 byte 數組。 |
void | reset() 將此流重新定位到最后一次對此輸入流調用 mark 方法時的位置。 |
long | skip(long n) 跳過和丟棄此輸入流中數據的 n 個字節。 |
5.2、FileInputStream與FileOutputStream
package com.pb.io.demo5;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;/** * 使用字節流復制文件 * */public class FileOutputAndFileInputStreamDemo { public static void main(String[] args) { File source=new File("d://1.jpg"); File objFile=new File("d://4.jpg"); InputAndOutput2(source,objFile); } public static void InputAndOutput(File source,File objFile){ //聲明字節流輸入,輸出對象 FileInputStream fis=null; FileOutputStream fos=null; try { fis=new FileInputStream(source); fos=new FileOutputStream(objFile); //聲明緩沖區 byte [] buf=new byte[1024]; int len=0; while((len=fis.read(buf))!=-1){ fos.write(buf, 0, len); } System.out.println("=======讀寫完成========"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ try { if(fos!=null) fos.close(); } catch (IOException e) { e.printStackTrace(); } try { if (fis!=null) fis.close(); } catch (IOException e) { e.printStackTrace(); } } } /* * 不建議使用 */ public static void InputAndOutput2(File source,File objFile){ //聲明字節流輸入,輸出對象 FileInputStream fis=null; FileOutputStream fos=null; try { fis=new FileInputStream(source); fos=new FileOutputStream(objFile); //聲明大小剛剛緩沖區 byte [] buf=new byte[fis.available()]; //不建議使用available fis.read(buf); fos.write(buf,0,buf.length); System.out.println("=======讀寫完成========"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ try { if(fos!=null) fos.close(); } catch (IOException e) { e.printStackTrace(); } try { if (fis!=null) fis.close(); } catch (IOException e) { e.printStackTrace(); } } }}
6.1、示例復制.mp3
package com.pb.io.demo5;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;public class BufferedStreamDemo { public static void main(String[] args) { File file1=new File("d://gm.mp3"); File file2=new File("d://mg.mp3"); copy1(file1,file2); } public static void copy1(File file1,File file2){ //聲明字節流緩沖區對象 BufferedOutputStream bos=null; BufferedInputStream bis=null; try { bis=new BufferedInputStream(new FileInputStream(file1)); bos=new BufferedOutputStream(new FileOutputStream(file2)); //聲明緩沖區大小 int by=0; while((by=bis.read())!=-1){ bos.write(by); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ try { if(bos!=null) bos.close(); } catch (IOException e) { e.printStackTrace(); } try { if(bis!=null) bis.close(); } catch (IOException e) { e.printStackTrace(); } } }}
6.2、自定義
package com.pb.io.demo5;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;public class MyBufferedStream { private InputStream is; private byte[] buf = new byte[1024]; private int pos = 0; private int count = 0; public MyBufferedStream(InputStream is) { this.is = is; } /* * 一次讀一個字節,從緩沖區的(字節數組)獲取 */ public int myRead() throws IOException { // 通過in對象讀取硬盤上的數據,并存在buf中 if (count == 0) { count = is.read(buf); if (count < 0) { return -1; } pos = 0; byte b = buf[pos]; count--; pos++; return b & 0xff; } else if (count > 0) { byte b = buf[pos]; count--; pos++; return b & 0xff; } return -1; } public void myClose() throws IOException { is.close(); } public static void main(String[] args) { File file1 = new File("d://gm.mp3"); File file2 = new File("d://kk.mp3"); copy1(file1, file2); } public static void copy1(File file1, File file2) { // 聲明字節流緩沖區對象 BufferedOutputStream bos = null; MyBufferedStream mbs = null; try { mbs = new MyBufferedStream(new FileInputStream(file1)); bos = new BufferedOutputStream(new FileOutputStream(file2)); // 聲明緩沖區大小 int by = 0; while ((by = mbs.myRead()) != -1) { bos.write(by); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (bos != null) bos.close(); } catch (IOException e) { e.printStackTrace(); } try { mbs.myClose(); } catch (IOException e) { e.printStackTrace(); } } }}
7.1、字節流轉換字符流
InputStreamReader 是字節流通向字符流的橋梁:它使用指定的 charset
讀取字節并將其解碼為字符。它使用的字符集可以由名稱指定或顯式給定,或者可以接受平臺默認的字符集。
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
OutputStreamWriter 是字符流通向字節流的橋梁:可使用指定的 charset
將要寫入流中的字符編碼成字節。它使用的字符集可以由名稱指定或顯式給定,否則將接受平臺默認的字符集。
Writer out = new BufferedWriter(new OutputStreamWriter(System.out));
7.2、示例
接收鍵盤輸入,使用轉換流實現
package com.pb.io.demo6;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;/** * 接收鍵盤輸入,并將內容寫入文件 * */public class Demo { public static void main(String[] args) { BufferedReader br=null; BufferedWriter bw=null; try { //聲明輸入流,使用轉換流實現 br=new BufferedReader(new InputStreamReader(System.in)); //聲明輸出流,使用轉換流實現 bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("d://t.txt"))); //接收鍵盤錄入 String str=null; System.out.println("請輸入要寫入文件的內容,輸入over結束!"); //輸入over結束 while(!(str=br.readLine()).equals("over")){ bw.write(str); bw.newLine(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ try { if(bw!=null) bw.close(); } catch (IOException e) { e.printStackTrace(); } try { if(br!=null) br.close(); } catch (IOException e) { e.printStackTrace(); } } }}
1、明確源和目的
源:輸入流。InputStream,Reader
目的:輸出流 .OutputStream,Writer
2、操作的數據是否為純文本
是:字符流。Reader、Writer
不是:字節流。InputStream、OutputStream
3、當體系明確后,在明確要使用哪個具體對象。
通過設備來進行區別。
源設備:內存、硬盤、鍵盤
目的設備:內存、硬盤、控制臺
9.1、示例
//設置輸入流的 System.setIn(new FileInputStream("d://demo.txt")); //設置的輸出流的方向 System.setOut(new PrintStream("d://zz.txt"));
10.1、示例
package com.pb.io.demo6;import java.util.Properties;public class Demo1 { public static void main(String[] args) { Properties prop=System.getProperties(); prop.list(System.out); //可以設置為輸出流對象new PrintWriter(文件) }}
-- listing properties --java.runtime.name=Java(TM) SE Runtime Environmentsun.boot.library.path=C:/Java/jre1.8.0_60/binjava.vm.version=25.60-b23java.vm.vendor=Oracle Corporationjava.vendor.url=http://java.oracle.com/path.separator=;java.vm.name=Java HotSpot(TM) 64-Bit Server VMfile.encoding.pkg=sun.iouser.script=user.country=CNsun.java.launcher=SUN_STANDARDsun.os.patch.level=java.vm.specification.name=Java Virtual Machine Specificationuser.dir=F:/work/IODemojava.runtime.version=1.8.0_60-b27java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironmentjava.endorsed.dirs=C:/Java/jre1.8.0_60/lib/endorsedos.arch=amd64java.io.tmpdir=C:/Users/ADMINI~1/AppData/Local/Temp/line.separator=java.vm.specification.vendor=Oracle Corporationuser.variant=os.name=Windows 7sun.jnu.encoding=GBKjava.library.path=C:/Java/jre1.8.0_60/bin;C:/Windows/Su...java.specification.name=Java Platform API Specificationjava.class.version=52.0sun.management.compiler=HotSpot 64-Bit Tiered Compilersos.version=6.1user.home=C:/Users/Administratoruser.timezone=java.awt.printerjob=sun.awt.windows.WPrinterJobfile.encoding=UTF-8java.specification.version=1.8user.name=Administratorjava.class.path=F:/work/IODemo/binjava.vm.specification.version=1.8sun.arch.data.model=64java.home=C:/Java/jre1.8.0_60sun.java.command=com.pb.io.demo6.Demo1java.specification.vendor=Oracle Corporationuser.language=zhawt.toolkit=sun.awt.windows.WToolkitjava.vm.info=mixed modejava.version=1.8.0_60java.ext.dirs=C:/Java/jre1.8.0_60/lib/ext;C:/Window...sun.boot.class.path=C:/Java/jre1.8.0_60/lib/resources.jar...java.vendor=Oracle Corporationfile.separator=/java.vendor.url.bug=http://bugreport.sun.com/bugreport/sun.cpu.endian=littlesun.io.unicode.encoding=UnicodeLittlesun.desktop=windowssun.cpu.isalist=amd64
新聞熱點
疑難解答