*11-IO流(字符流-缓冲区-解释)

//创建一个临时容器,用于缓存读取到的字符。
char[] buf = new char[BUFFER_SIZE];//这就是缓冲区。 是自己new出来的。提高效率

Java就把这个缓冲区封装成一个对象,其实把缓冲区封装成对象,就是在一个类中封装一个数组。

对于读和写都封装成了对象。

IO包中:








*12-IO流(字符流-缓冲区-BufferedWriter)

之前缓冲区,是自己new出来的,

系统给了,bufferwriter,bufferreader、





缓冲区创建的时候,必须指定要缓存的对象,也就是Writer对象。


以前这样写:



提高效率,就要加缓冲区了:



注意:关掉buffer的时候也会把流给关掉。



package cn.itcast.p2.io.charstream.buffer;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedWriterDemo {

	private static final String LINE_SEPARATOR = System.getProperty("line.separator");

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {

		FileWriter fw = new FileWriter("buf.txt");
		
		//为了提高写入的效率。使用了字符流的缓冲区。
		//创建了一个字符写入流的缓冲区对象,并和指定要被缓冲的流对象相关联
		BufferedWriter bufw = new BufferedWriter(fw);
		
		//使用缓冲区的写入方法将数据先写入到缓冲区中。
//		bufw.write("abcdefq"+LINE_SEPARATOR+"hahahha");      效果和bufw.newLine();一样,其实调用的也是system.
//		bufw.write("xixiixii");
//		bufw.newLine();
//		bufw.write("heheheheh");
		
		for(int x=1; x<=4; x++){
			bufw.write("abcdef"+x);
			bufw.newLine();
			bufw.flush();
		}
		
		
		//使用缓冲区的刷新方法将数据刷目的地中。
//		bufw.flush();
		
		
		//关闭缓冲区。其实关闭的就是被缓冲的流对象。
		bufw.close();
		
//		fw.write("hehe");
		
//		fw.close();
	}

}

*13-IO流(字符流-缓冲区-BufferedReader)

读怎么读?

以前的读法:

	public static void demo() throws FileNotFoundException, IOException {
		FileReader fr = new FileReader("buf.txt");
		
		char[] buf = new char[1024];
		
		int len = 0;
		while((len=fr.read(buf))!=-1){
			System.out.println(new String(buf,0,len));
		}
		
		fr.close();
	}


新的:





读文本:可以一个一个字符读,也可以读完放数组中,也可以一行一行读。



public class BufferedReaderDemo {

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {

		FileReader fr = new FileReader("buf.txt");
		
		BufferedReader bufr = new BufferedReader(fr);
		
		String line = null;
		
		while((line=bufr.readLine())!=null){
			System.out.println(line);
		}
		/*
		String line1 = bufr.readLine();
		System.out.println(line1);
		String line2 = bufr.readLine();
		System.out.println(line2);
		String line3 = bufr.readLine();
		System.out.println(line3);
		String line4 = bufr.readLine();
		System.out.println(line4);
		String line5 = bufr.readLine();
		System.out.println(line5);
		*/
		
		
		bufr.close();
		
		
	}


*14-IO流(字符流-缓冲区-BufferedReader-readLine方法原理)


read ,read()和read(char[])  ——硬盘里面读


bufferread 重写了父类的read()和read(char[]) ——缓冲区读,内存操作,快。


bufr.read():一次只能读一个字符;

bufr.readLine():一次读一行。








*15-IO流(字符流-缓冲区-复制文本文件)

一种方法:


第二种方法:读一行,写一行。




这样会只存在一行里面。



package cn.itcast.p3.io.charstream.buffer.test;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CopyTextByBufTest {

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {

		FileReader fr = new FileReader("buf.txt");		
		BufferedReader bufr = new BufferedReader(fr);
		
		FileWriter fw = new FileWriter("buf_copy.txt");
		BufferedWriter bufw = new BufferedWriter(fw);
		
		
		String line = null;
		while((line=bufr.readLine())!=null){
			bufw.write(line);
			bufw.newLine();
			bufw.flush();
		}
		
		
		
		
		/*
		int ch = 0;
		
		while((ch=bufr.read())!=-1){
			
			bufw.write(ch);
		}
		*/
		bufw.close();
		bufr.close();
	}

}


*16-IO流(字符流-缓冲区-自定义MyBufferedReader-read方法)



1.read方法:


/**
 * 自定义的读取缓冲区。其实就是模拟一个BufferedReader.
 * 
 * 分析:
 * 缓冲区中无非就是封装了一个数组,
 * 并对外提供了更多的方法对数组进行访问。
 * 其实这些方法最终操作的都是数组的角标。
 * 
 * 缓冲的原理:
 * 其实就是从源中获取一批数据装进缓冲区中。
 * 在从缓冲区中不断的取出一个一个数据。
 * 
 * 在此次取完后,在从源中继续取一批数据进缓冲区。
 * 当源中的数据取光时,用-1作为结束标记。 
 * 
 * 
 * @author Administrator
 *
 */
public class MyBufferedReader extends Reader {

	private Reader r;
	
	//定义一个数组作为缓冲区。
	private char[] buf = new char[1024];
	
	//定义一个指针用于操作这个数组中的元素。当操作到最后一个元素后,指针应该归零。	
	private int pos = 0;	
	
	
	//定义一个计数器用于记录缓冲区中的数据个数。 当该数据减到0,就从源中继续获取数据到缓冲区中。
	private int count = 0;
	
	
	MyBufferedReader(Reader r){
		this.r = r;
	}
	
	/**
	 * 该方法从缓冲区中一次取一个字符。 
	 * @return
	 * @throws IOException
	 */
	public int myRead() throws IOException{
		
		if(count==0){
			count = r.read(buf);
			pos = 0;
		}
		if(count<0)
			return -1;
		
		char ch = buf[pos++];
		
		count--;
		
		return ch;
		
		/*
		//1,从源中获取一批数据到缓冲区中。需要先做判断,只有计数器为0时,才需要从源中获取数据。
		if(count==0){
			count = r.read(buf);
			
			if(count<0)
				return -1;
			
			//每次获取数据到缓冲区后,角标归零.
			pos = 0;
			char ch = buf[pos];
			
			pos++;
			count--;
			
			return ch;
			
		}else if(count>0){
			
			char ch = buf[pos];
			
			pos++;
			count--;
			
			return ch;
			
		}*/
		
	}




*17-IO流(字符流-缓冲区-自定义MyBufferedReader-readLine方法)

readLine()的实现。

public String myReadLine() throws IOException{
		
		StringBuilder sb = new StringBuilder();
		
		int ch = 0;
		while((ch = myRead())!=-1){
			
			if(ch=='\r')
				continue;
			if(ch=='\n')
				return sb.toString();
			//将从缓冲区中读到的字符,存储到缓存行数据的缓冲区中。
			sb.append((char)ch);
			
		}		
		
		if(sb.length()!=0)
			return sb.toString();
		return null;
	}

MyBufferReaderDemo:

package cn.itcast.p4.io.charstream.mybuffer;

import java.io.FileReader;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;

public class MyBufferedReaderDemo {

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {

		FileReader fr = new FileReader("buf.txt");
		
		MyBufferedReader bufr = new MyBufferedReader(fr);
		
		String line = null;
		
		while((line=bufr.myReadLine())!=null){
			System.out.println(line);
		}
		
		bufr.myClose();
		
		
		Collections.reverseOrder();
		HashMap map = null;
		map.values();
		
		
	}

}

MyBufferReader:

package cn.itcast.p4.io.charstream.mybuffer;

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

/**
 * 自定义的读取缓冲区。其实就是模拟一个BufferedReader.
 * 
 * 分析:
 * 缓冲区中无非就是封装了一个数组,
 * 并对外提供了更多的方法对数组进行访问。
 * 其实这些方法最终操作的都是数组的角标。
 * 
 * 缓冲的原理:
 * 其实就是从源中获取一批数据装进缓冲区中。
 * 在从缓冲区中不断的取出一个一个数据。
 * 
 * 在此次取完后,在从源中继续取一批数据进缓冲区。
 * 当源中的数据取光时,用-1作为结束标记。 
 * 
 * 
 * @author Administrator
 *
 */
public class MyBufferedReader extends Reader {

	private Reader r;
	
	//定义一个数组作为缓冲区。
	private char[] buf = new char[1024];
	
	//定义一个指针用于操作这个数组中的元素。当操作到最后一个元素后,指针应该归零。	
	private int pos = 0;	
	
	
	//定义一个计数器用于记录缓冲区中的数据个数。 当该数据减到0,就从源中继续获取数据到缓冲区中。
	private int count = 0;
	
	
	MyBufferedReader(Reader r){
		this.r = r;
	}
	
	/**
	 * 该方法从缓冲区中一次取一个字符。 
	 * @return
	 * @throws IOException
	 */
	public int myRead() throws IOException{
		
		if(count==0){
			count = r.read(buf);
			pos = 0;
		}
		if(count<0)
			return -1;
		
		char ch = buf[pos++];
		
		count--;
		
		return ch;
		
		/*
		//1,从源中获取一批数据到缓冲区中。需要先做判断,只有计数器为0时,才需要从源中获取数据。
		if(count==0){
			count = r.read(buf);
			
			if(count<0)
				return -1;
			
			//每次获取数据到缓冲区后,角标归零.
			pos = 0;
			char ch = buf[pos];
			
			pos++;
			count--;
			
			return ch;
			
		}else if(count>0){
			
			char ch = buf[pos];
			
			pos++;
			count--;
			
			return ch;
			
		}*/
		
	}
	
	public String myReadLine() throws IOException{
		
		StringBuilder sb = new StringBuilder();
		
		int ch = 0;
		while((ch = myRead())!=-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 {
		
		r.close();
	}

	@Override
	public int read(char[] cbuf, int off, int len) throws IOException {
		
		return 0;
	}

	@Override
	public void close() throws IOException {
	}
}


*18-IO流(字符流-缓冲区-装饰设计模式)


装饰设计模式:
对一组对象的功能进行增强时,就可以使用该模式进行问题的解决。


package cn.itcast.p5.wrapper;

public class PersonDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		Person p = new Person();
//		p.chifan();
		
		NewPerson p1 = new NewPerson(p);
		p1.chifan();
		
		NewPerson2 p2 = new NewPerson2();
		p2.chifan();
	}

}

class Person{
	void chifan(){
		System.out.println("吃饭");
	}
}
//这个类的出现是为了增强Person而出现的。
class NewPerson{
	private Person p ;
	NewPerson(Person p){
		this.p = p;
	}
	
	public void chifan(){
		System.out.println("开胃酒");
		p.chifan();
		System.out.println("甜点");
		
	}

}

class NewPerson2 extends Person{
	public void chifan(){
		System.out.println("开胃酒");
		super.chifan();
		System.out.println("甜点");
	}
}

装饰好呢?还是继承好呢?

装饰和继承都能实现一样的特点:进行功能的扩展增强。 


有什么区别呢?


*19-IO流(字符流-缓冲区-装饰设计模式和继承的区别)



有什么区别呢?


首先有一个继承体系。
Writer
|--TextWriter:用于操作文本
|--MediaWriter:用于操作媒体。

想要对操作的动作进行效率的提高。
按照面向对象,可以通过继承对具体的进行功能的扩展。 
效率提高需要加入缓冲技术。

Writer
|--TextWriter:用于操作文本
|--BufferTextWriter:加入了缓冲技术的操作文本的对象。
|--MediaWriter:用于操作媒体。
|--BufferMediaWriter:


到这里就哦了。但是这样做好像并不理想。
如果这个体系进行功能扩展,有多了流对象。
那么这个流要提高效率,是不是也要产生子类呢?是。这时就会发现只为提高功能,进行的继承,
导致继承体系越来越臃肿。不够灵活。 


重新思考这个问题?
既然加入的都是同一种技术--缓冲。
前一种是让缓冲和具体的对象相结合。 
可不可以将缓冲进行单独的封装,哪个对象需要缓冲就将哪个对象和缓冲关联。


class Buffer{
Buffer(TextWriter w)
{}

Buffer(MediaWirter w)
{

}
}
class BufferWriter extends Writer{
BufferWriter(Writer w)
{
}
}
Writer
|--TextWriter:用于操作文本
|--MediaWriter:用于操作媒体。
|--BufferWriter:用于提高效率。

装饰比继承灵活。


特点:装饰类和被装饰类都必须所属同一个接口或者父类。 


装饰设计模式。


*20-IO流(字符流-缓冲区-LineNumberReader)



















Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐