一、File***Stream和 Buffered***Stream
Buffered帶緩存區,提高了記憶體和記憶體之間的互動,減少了記憶體和磁盤之間的互動,效率更高。
二、MyBuffered
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class TestMyBufferedStream {
public static void main(String[] args) {
long time = System.currentTimeMillis();
BufferedInputOutputStreamTest.copyFile();
long cost = System.currentTimeMillis()-time;
System.out.println("buffered cost = "+cost);
time = System.currentTimeMillis();
try {
copyFile();
} catch (Exception e) {
e.printStackTrace();
}
cost = System.currentTimeMillis()-time;
System.out.println("myBuffered cost = "+cost);
static void copyFile() throws Exception{
MyBufferedInputStream mbis = new MyBufferedInputStream(new FileInputStream("c:/77.jpg"));
MyBufferedOutputStream mbos = new MyBufferedOutputStream(new FileOutputStream("c:/99.jpg"));
int value = 0;
while((value = mbis.read()) != -1){
mbos.write(value);
mbis.close();
mbos.flush();
mbos.close();
/**
* 自定義的帶緩沖區的位元組輸入流,模拟 java.io.BufferedInputStream
*
*/
public class MyBufferedInputStream {
//定義預設的緩沖區大小
public static final int DEFAULT_BUF_SIZE = 8192;
//位元組數組緩沖區
private byte[] buf;
//用于讀取資料源的位元組輸入流的引用,可以是任意的位元組輸入流
private InputStream is;
//記錄目前讀取到的位元組數組資料的下标
private int pos;
//用于記錄緩沖區中有效的位元組資料
private int count;
public MyBufferedInputStream(InputStream is) {
this.is = is;
buf = new byte[DEFAULT_BUF_SIZE];
public MyBufferedInputStream(InputStream is,int bufSize) {
buf = new byte[bufSize];
//最核心對外提供的read 方法 讀取下一個位元組的資料
//從buf 中取一個位元組的資料
public int read() throws Exception{
if(count == 0){//緩沖區沒有資料了
//一次性從通過is 讀取底層資料 到buf 中,并記錄讀取到了多少有效位元組資料。
count = is.read(buf);
//一種是 資料源還有資料,一種是資料源沒有資料了,傳回-1
if(count == -1)//return -1
return -1;
pos = 0;
//使用int 的低八位 儲存 讀取到的位元組資料。
int value = buf[pos] & 0xff;
pos ++;
count --;
return value;
}else{//緩沖區有資料
//包裝流的關閉問題,關閉的是被包裝的流。
public void close() throws Exception{
if(is != null){
is.close();
* 自定義的帶緩沖區的輸出流
class MyBufferedOutputStream{
private OutputStream os;
//用于記錄寫入緩沖區的位元組資料的個數,和目前待寫入數組元素的下标
public MyBufferedOutputStream(OutputStream os) {
this.os = os;
public MyBufferedOutputStream(OutputStream os,int bufSize) {
* 将value 的後八位寫出去
* @param value
public void write(int value) throws Exception{
//緩沖區滿了
if(pos == buf.length){
//将緩沖區的内容全部寫出去
os.write(buf);
//然後再将value 寫入下标pos = 0 的位置
buf[pos] = (byte)value;
//pos 永遠指向 待寫入資料的下标
}else{//緩沖區沒有滿
//将value 寫入pos 位置
public void flush() throws Exception{
if(pos != 0){
//将緩沖區中沒有寫出去的資料,重新整理到目的地
os.write(buf, 0, pos);
//
if(os != null){
//確定在關閉的時候,可以将緩沖區中的資料重新整理出去
flush();
os.close();
包裝流的關閉問題:
隻關閉包裝流即可,因為在關閉包裝流的方法中,對被包裝的流進行了關閉。
三、BufferedReader和BufferedWriter
帶緩沖區的字元流。緩沖區8192 個字元。 char[]
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedReaderWriterTest {
copyTextFile();
static void copyTextFile(){
FileReader fr = null;
BufferedReader br = null;
FileWriter fw = null;
BufferedWriter bw = null;
fr = new FileReader("./res/my_letter.txt");
br = new BufferedReader(fr);
fw = new FileWriter("./res/my_letter_copy.txt");
bw = new BufferedWriter(fw);
//用于讀取一行文本資料,如果方法傳回null 則表示讀取到了檔案的末尾
String str = br.readLine();
while(str != null){
bw.write(str);
//向輸出流中寫出一個目前系統的換行符
bw.newLine();
str = br.readLine();
}finally {
if(br != null){
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
if(bw != null){
bw.close();
if(fr != null){
fr.close();
if(fw != null){
fw.close();
readLine():用于讀取一行文本資料。當讀取到\r\n時候方法傳回。把讀取到的所有的内容傳回,傳回的内容中不包含 \r\n。
四、LineNumberReader
LineNumberReader:是BufferedReader 的子類。增加了用于記錄讀取到文本資料的多少行的功能。
import java.io.FileReader;
import java.io.LineNumberReader;
public class LineNumberReaderTest {
//将目前檔案的所有的内容,列印到控制台,輸出的時候,還有行号輸出。
public static void main(String[] args) throws Exception{
LineNumberReader lnr = new LineNumberReader(new FileReader("./src/com/bjsxt/io/LineNumberReaderTest.java"));
//設定起始行号
lnr.setLineNumber(100);
String str = null;
//讀取一行,并列印一行
while((str = lnr.readLine()) != null){
//獲得行号
int number = lnr.getLineNumber();
System.out.println(number + " "+str);
lnr.close();
五、裝飾設計模式
裝飾設計模式:帶緩沖區的位元組流,字元流都使用了該設計模式。
作用:增強擴充指定的類的。
public class DecorateTest {
SuperPeople people = new SuperPeople(new Person());
people.eat();
class Person{
void eat(){
System.out.println("人要吃飯,為了生存!");
//繼承擴充現有的類
class SuperPerson extends Person{
System.out.println("人吃飯不僅僅是為了生存,還是為了更好的生存!享受健康的生活");
//使用組合擴充現有類
//組合優于繼承:組合既可以擴充指定的類型,還可以是指定類型的子類型。
class SuperPeople {
//被擴充的類作為擴充類的執行個體成員 組合
private Person person;
public SuperPeople(Person person) {
this.person = person;
System.out.println("我喜歡吃魚!");
System.out.println("我喜歡羊腿+啤酒(不能太涼,慫人樂即可)!");
person.eat();
六、InputStreamReader 和 OutputStreamWriter
InputStreamReader:轉換流:從位元組到字元的轉換的流。字元流
解碼器--所有的字元流都以它為基礎進行工作。
public class InputStreamReader extends Reader
InputStreamReader 是位元組流通向字元流的橋梁:它使用指定的 charset 讀取位元組并将其解碼為字元。它使用的字元集可以由名稱指定或顯式給定,或者可以接受平台預設的字元集。
每次調用InputStreamReader 中的一個 read() 方法都會導緻從底層輸入流讀取一個或多個位元組。
InputStreamReader :給它提供一堆位元組資料,它可以根據字元集傳回給你一堆字元資料。
吃的是位元組,擠的是字元。
所有的字元輸出流,最終寫到磁盤中的是位元組資料。
write(String)
OutputStreamWriter: 字元輸出流
public class OutputStreamWriter extends Writer
OutputStreamWriter 是字元流通向位元組流的橋梁:可使用指定的 charset 将要寫入流中的字元編碼成位元組。它使用的字元集可以由名稱指定或顯式給定,否則将接受平台預設的字元集。
每次調用write() 方法都會導緻在給定字元(或字元集)上調用編碼轉換器。在寫入底層輸出流之前,得到的這些位元組将在緩沖區中累積。可以指定此緩沖區的大小,不過,預設的緩沖區對多數用途來說已足夠大。注意,傳遞給 write() 方法的字元沒有緩沖。
為了獲得最高效率,可考慮将OutputStreamWriter 包裝到 BufferedWriter 中,以避免頻繁調用轉換器。
總結:InputStreamReader 是所有的字元輸入流位元組到字元轉換的基礎。解碼轉換器。是所有的字元輸入流的實作都依賴于該類提供的解碼的功能。
OutputStreamWriter 是所有的字元輸出流字元到位元組轉換的基礎。編碼轉換器。是所有的字元輸出流的實作都依賴于該類提供的編碼的功能。
位元組資料:密文
字元集:整數和字元對應的一個映射表
位元組資料對應的字元序列:明文
編碼:字元-->位元組
解碼:位元組-->字元
例1:
import java.io.InputStreamReader;
public class InputStreamReaderTest {
public static void main(String[] args) throws Exception {
test1();
static void test() throws Exception{
//如果不顯示指定字元集,使用平台預設的字元集工作的 轉換流,給它提供位元組資料
//可以顯式指定字元集
InputStreamReader isr = new InputStreamReader(new FileInputStream("./res/3.txt"),"utf-8");
BufferedReader br = new BufferedReader(isr);
System.out.println(str);
//接收鍵盤的輸入,将輸入的内容寫入到指定的檔案中。如果輸入了bye,那麼輸入終止
static void test1() throws Exception{
//将鍵盤輸入的位元組流,轉換為字元流
InputStreamReader isr = new InputStreamReader(System.in);
//為了提高效率 使用BufferedReader 包一層
BufferedWriter bw = new BufferedWriter(new FileWriter("./res/input.txt"));
//接收鍵盤的輸入了,當回車的時候,該方法傳回。
while(!"bye".equals(str)){
bw.flush();
例2:
import java.io.OutputStreamWriter;
public class OutputStreamWriterTest {
test();
//使用平台預設的字元集進行編碼 成位元組,通過out 位元組流,将 編碼得到的位元組寫出到底層
// OutputStreamWriter osw = new OutputStreamWriter(out)
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("./res/6.txt"),"UTF-8");
BufferedWriter bw = new BufferedWriter(osw);
//寫到bw 中的緩沖區中
bw.write("月上柳梢頭,人約黃昏後!");
七、擴充卡設計模式
擴充卡設計模式:
InputStreamReader :吃的是位元組,産出的是字元。
擴充卡:Adapter:
筆記本和手機充電器中的擴充卡的作用:吃的是生活電壓(220V),産出的是我們筆記本,和手機充電需要的電壓。
有類擴充卡設計模式和對象擴充卡設計模式。
public class AdapterTest {
// MyAdapter adapter = new MyAdapter();
// adapter.run();
MyObjAdapter adapter = new MyObjAdapter(new Adaptee());
adapter.run();
//底層工作的電壓
class Adaptee{
int run(){
System.out.println("我提供了220V的電壓");
return 220;
//類擴充卡設計模式 使用繼承
class MyAdapter extends Adaptee{
//筆記本的工作電壓為22V
int run() {
int num = super.run();
System.out.println("220V電壓被轉換為22V工作電壓了!");
return num/10;
//對象擴充卡設計模式--使用組合方式,把被适配的對象作為成員存在
class MyObjAdapter{
Adaptee adaptee;
public MyObjAdapter(Adaptee adaptee) {
this.adaptee = adaptee;
int num = adaptee.run();