黑马程序员_学习笔记第19天——缓冲区、转换流、字节流

---------------------- ASP.Net+Android+IOS开发、 href="http://edu.csdn.net"target="blank">.Net培训、期待与您交流! ----------------------

1、BufferedWriter

缓冲区的出现是为了提高流的操作效率而出现的,所以在创建缓冲区之前,必须要先有流对象。

该缓冲区中提供了一个跨平台的换行符:newLine();

	public static void main(String[] args) throws IOException{
		//创建一个字符写入流对象
		FileWriter fw = new FileWriter("d:\\buf.txt");
		//为了提高字符写入流效率,加入了缓冲技术
		//只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可
		BufferedWriter bufw = new BufferedWriter(fw);
		
		for(int x=0 ; x<5; x++) {
			bufw.write("abcd"+x);
			bufw.newLine();
			bufw.flush();
			//记住,只要用到缓冲区,就要记得刷新
		}
		//其实关闭缓冲区,就是在关闭缓冲区中的流对象
		bufw.close();
	}

2、字符读取流缓冲区BufferedReader

该缓冲区提供了一个一次读一行的方法readLine,方便于对文本数据的获取。当返回null时,表示读到文件末尾。

readLine方法返回的时候只返回回车符之前的数据内容,并不返回回车符。

readLine方法原理:无论是读一行,获取读取多个字符,其实最终都是在硬盘上一个一个读取,所以最终使用的还是read方法一次读一个的方法。

	public static void main(String[] args) throws IOException{
		//创建一个读取流对象和文件相关联
		FileReader fr = new FileReader("d:\\buf.txt");
		//为了提高效率,加入缓冲技术,将字符读取流对象作为参数传递给缓冲对象的构造函数
		BufferedReader bufr = new BufferedReader(fr);
		
		String line = null;
		
		while((line = bufr.readLine())!=null) {
			System.out.println(line);
		}
		bufr.close();
	}
3、通过缓冲区复制一个.java文件

public class CopyTextByBuf {

	public static void main(String[] args) {
		
		BufferedReader bufr = null;
		BufferedWriter bufw = null;
		
		try {
			bufr = new BufferedReader(new FileReader("d:\\javatest\\Demo.java"));
			bufw = new BufferedWriter(new FileWriter("d:\\copy_Demo.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("写入关闭出错啦");
			}
			
		}

	}

}

4、自己编写readLine方法

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();
	}
}

5、装饰设计模式:

当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,并提供加强功能,那么自定义的该类称为装饰类。

装饰类通常会通过构造方法接收被装饰的对象,并基于被装饰的对象的功能,提供更强的功能。

装饰模式比继承要灵活,避免了继承体系臃肿,而且降低了类与类之间的关系。

装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能,所以装饰类和被装饰类通常都属于一个体系中的。

class MyBufferedReader extends Reader{
	private Reader r ;
	MyBufferedReader(Reader 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 int read(char[] cbuf,int off,int len) throws IOException{
		return r.read(cbuf,off,len);
	}
	public void close() throws IOException{
		r.close();
	}
}

6、LineNumberReader带行号的缓冲区

	public static void main(String[] args) throws IOException{
		
		FileReader fr = new FileReader("d:\\buf.txt");
		LineNumberReader lnr = new LineNumberReader(fr);
		
		String line = null;
		lnr.setLineNumber(100);//行号从100开始
		while((line=lnr.readLine())!=null) {
			System.out.println(lnr.getLineNumber()+":"+line);
		}
		lnr.close();

	}

7、自己编写LineNumberReader

public class MyLineNumberReaderDemo {

	public static void main(String[] args) throws IOException{
		FileReader fr = new FileReader("d:\\buf.txt");
		MyLineNumberReader mlnr = new MyLineNumberReader(fr);
		String line = null;
		mlnr.mySetLineNumber(100);
		while((line=mlnr.myReadLine())!=null){
			System.out.println(mlnr.myGetLineNumber()+":"+line);
		}
		mlnr.close();
	}

}
class MyLineNumberReader extends MyBufferedReader {
	private int lineNumber;
	MyLineNumberReader(Reader r ) {
		super(r);
	}
	public String myReadLine() throws IOException{
		lineNumber++;
		return super.myReadLine();
	}
	public void mySetLineNumber(int lineNumber) {
		this.lineNumber = lineNumber;
	}
	public int myGetLineNumber() {
		return lineNumber;
	}
}
/*
class MyLineNumberReader {
	private Reader r ;
	private int lineNumber;
	
	MyLineNumberReader(Reader r ) {
		this.r = r;
	}
	public String myReadLine() throws IOException{
		lineNumber++;
		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 mySetLineNumber(int lineNumber) {
		this.lineNumber = lineNumber;
	}
	public int myGetLineNumber() {
		return lineNumber;
	}
	public void myClose() throws IOException{
		r.close();
	}
	
}
*/

8、字节流

public static void readFile_3() throws IOException {
		FileInputStream fis = new FileInputStream("d:\\1.txt");
		byte[] b =new byte[fis.available()];//定义一个刚刚好的缓冲区,不用再循环了。但是要慎用,太大的文件会内存溢出
		fis.read(b);
		System.out.println(new String(b));
		fis.close();
	}
	public static void readFile_2() throws IOException {
		FileInputStream fis = new FileInputStream("d:\\1.txt");
		byte[] b =new byte[1024];
		int len = 0;
		while((len=fis.read(b))!=-1) {
			System.out.println(new String(b,0,len));
		}
		fis.close();
	}
	public static void readFile_1() throws IOException {
		FileInputStream fis = new FileInputStream("d:\\buf.txt");
		int ch = 0;
		while((ch=fis.read())!=-1) {
			System.out.print((char)ch);
		}
		fis.close();
	}
	public static void writeFile_1() throws IOException {
		FileOutputStream fos = new FileOutputStream("d:\\1.txt");
		fos.write("abcdefg".getBytes());
		fos.close();
	}
9、练习:复制图片
/*
 复制一个图片
 思路:
1、用字节读取流对象和图片关联
2、用字符写入流对象创建一个图片文件,用于存储获取到的图片数据
3、通过循环读写,完成数据的存储
4、关闭资源
*/
public class CopyPicDemo {

	public static void main(String[] args) {
		FileInputStream fis = null;
		FileOutputStream fos = null;
		try {
			fis = new FileInputStream("c:\\1.jpg");
			fos = new FileOutputStream("c:\\2.jpg");
			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("写入异常");
			}
		}

	}

}

10、自定义BufferedInputStream

class MyBufferedInputStream {
	private InputStream in ;
	private byte[] buf = new byte[1024];
	private int pos =0,count = 0;
	MyBufferedInputStream(InputStream in) {
		this.in = in ;
	}
	//一次读一个字节,从缓冲区(字节数组)获取
	public int myRead() throws IOException{
		//通过in对象读取硬盘上数据,并存储buf中
		if(count==0) {
			count = in.read(buf);
			if(count<0)
				return -1;
			pos = 0;
			byte b = buf[pos];
			count--;
			pos++;
			return b&255;
		}
		else if (count>0) {
			byte b = buf[pos];
			count--;
			pos++;
			return b&0xff;
		}
		return -1;
	}
	public void myClose() throws IOException {
		in.close();
	}
}
11、读取键盘录入

System.out:对应的是标准输出设备,控制台

System.in:对应的标准输入设备:键盘

//键盘录入,读到“over”时停止
public class ReadInDemo1 {

	public static void main(String[] args) throws IOException{
		//获取键盘录入对象
//		InputStream in = System.in;
		//将字节流对象转成字符流对象,使用转换流InputStreamReader,这是字节通向字符的桥梁
//		InputStreamReader isr = new InputStreamReader(in);
		//为了提高效率,将字符串进行缓冲区技术高效操作,使用BufferedReader
//		BufferedReader bfr = new BufferedReader(isr);
		//键盘录入的最常见写法、
		BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));
		
		/*OutputStream out = System.out ;
		OutputStreamWriter osw = new OutputStreamWriter(out);
		BufferedWriter bfw = new BufferedWriter(osw);*/
		
		BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(System.out));
		
		String line =null;
		while((line=bfr.readLine())!=null) {
			if("over".equals(line))
				break;
			bfw.write(line.toUpperCase());
			bfw.newLine();
			bfw.flush();
				
		}
		bfr.close();
		
		/*
		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);
		}
		*/

	}

}

12、流操作的基本规律通过三个明确来完成

1)明确源和目的

源:输入流  InputStream  Reader

目的:输出流  OutputStream  Writer

2)操作的数据是否是纯文本

是:字符流

不是:字节流

3)当体系明确后,在明确要使用哪个具体的对象

通过设备来进行区分

源设备:内存,硬盘,键盘

目的设备:内存,硬盘,控制台

/*
1、
源:键盘录入
目的:控制台
2、需求:想把键盘录入的数据存储到一个文件中
源:键盘
目的:文件
3、
需求:想要将一个文件的数据打印在控制台上
源:文件
目的:控制台
*/
public class TransStreamDemo {

	public static void main(String[] args) throws IOException{
		BufferedReader bufr = new BufferedReader(new InputStreamReader(new FileInputStream("d:\\1.txt")));
		BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
//		BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
//		BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("d:\\3.txt")));
		
		String line = null;
		while((line=bufr.readLine())!=null) {
			if("over".equals(line))
				break;
			bufw.write(line.toUpperCase());
			bufw.newLine();
			bufw.flush();
		}
		bufr.close();
		bufw.close();

	}

}


13、将一个文本文件中数据存储到另一个文件中,复制文件

1)

源:因为是源,所以使用读取流 InputStream  Reader

是不是操作文本文件?是!这时就可以选择Reader。这样体系就明确了。


接下来明确要使用该体系中的哪个对象

明确设备:硬盘,上一个文件

Reader体系中可以操作文件的对象是FileReader


是否需要提高效率:是!加入Reader体系中缓冲区BufferedReader

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

BufferedReader bufr = new BufferedReader(fr);

2)

目的:OutputStream Writer

是否是纯文本?是!Writer

设备:硬盘,一个文件

Writer体系中可以操作文件的对象FileWriter

是否需要提高效率:是!加入Writer体系中缓冲区BufferedWriter

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

BufferedWriter bufw = new BufferedWriter(fw);


14、将键盘录入的数据保存到一个文件中

1)

源:InputStream Reader

是否是纯文本文件?是,Reader

设备:键盘,对应的对象是System.in

需转成字符流按照字符串操作最方便。用Reader体系中转换流InputStreamReader 

InputStreamReader isr = new InputStreamReader(System.in);

需要提高效率吗?需要,BufferedReader 

BufferedReader bufr = new BufferedReader(isr);

2)

目的:OutputStream Writer 

是否是纯文本?是,Writer

设备:硬盘,一个文件,使用FileWriter

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

需要提高效率吗?需要,BufferedWriter

BufferedWriter bufw = new BufferedWriter(fw);


15、扩展:想要把录入的数据按照指定的编码表(utf-8)将数据存到文件中

目的:OutputStream   Writer

是否是纯文本?是,Writer

设备:硬盘,一个文件,使用FileWriter

但是FileWriter是使用的默认编码表GBK

但是存储时,需要加入指定编码表utf-8,而指定的编码表只有转换流可以指定

所以要使用的对象是OutputStreamWriter

而该转换流对象要接收一个字节输出流,而且还可以操作文件的字节输出流,FileOutputStream

OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d.txt"),"UTF-8");

需要高效吗?需要  BufferedWriter bufw = new BufferedWriter(osw);

所以,转换流是字符与字节之间的桥梁,通常,涉及到字符编码转换时,需要用到转换流。

16、System.setIn(new FileInputStream("1.txt"));//设置System.in由键盘录入改为1.txt的文件

System.setOut(new PrintStream("zzz.txt"));//设置System.out由控制台改为“zzz.txt”的文件

17、将异常信息存入日志文件中去

public static void main(String[] args) {
		try {
			int[] arr = new int[2];
			System.out.println(arr[3]);
		}catch(ArrayIndexOutOfBoundsException e) {
			try {
				Date d = new Date();
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				String s = sdf.format(d);
				
				PrintStream ps = new PrintStream("d:\\exception.log");
				ps.println(s);
				System.setOut(ps);
			}catch(IOException ex) {
				throw new RuntimeException("日志文件创建失败");
			}
			e.printStackTrace(System.out);
		}

	}

18、将系统信息存入到指定文件中去

public static void main(String[] args) throws IOException{
		Properties prop = System.getProperties();
		prop.list(new PrintStream("d:\\sysinfo.txt"));

	}


---------------------- ASP.Net+Android+IOS开发、 href="http://edu.csdn.net"target="blank">.Net培训、期待与您交流! ----------------------详细请查看: http://edu.csdn.net
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值