天天看點

2018-06-06 第三十一天

一、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();

繼續閱讀