【黑马程序员】IO流(二) 第二十天

-------  android培训java培训java学习型技术博客、期待与您交流! ----------

知识点


01)BufferWriter

/*
 * BufferWriter:
 * 为了提高字符写入流效率,加入了缓冲技术。
 * 只需要将要被提高效率的流对象作为参数传递给缓冲区的构造函数即可。
 * newLine():写入一个行分隔符。行分隔符字符串由系统属性 line.separator 定义,并且不一定是单个新行 ('\n') 符。
 */
public class BufferWriterDemo {
	public static void main(String[] args) {
		method();
	}
	public static void method(){
		FileWriter fw = null;//创建一个引用。
		BufferedWriter bufw = null;
		try{
			fw = new FileWriter("buf.txt");//初始化流对象。
			//为了提高字符写入流效率,加入了缓冲技术。
			//只需要将要被提高效率的流对象作为参数传递给缓冲区的构造函数即可。
			bufw = new BufferedWriter(fw);
			for (int i = 1; i <= 5; i++){
				bufw.write(i + "   BufferWriter");
				bufw.newLine();//写入一个行分隔符。
			}
		}catch(IOException e){
			throw new RuntimeException("读取失败");
		}finally{
			try {
				if(bufw != null)
					//记住:只要用掉缓冲区,就要记得使用刷新。
					bufw.close();//其实关闭缓冲区,就是在关闭缓冲区中的流对象。fw.close()就不需要再关闭。
			} catch (IOException e) {
				throw new RuntimeException("读取关闭失败");
			}
		}
	}
}
运行结果如下图所示:


02)BufferedReader

/*
 * 字符读取流缓冲区:
 * 该缓冲区提供了一个一次读一行的方法。(readLine()),方法于对文本数据的获取。
 * 当返回null时,表示读到文件末尾。
 */
public class BufferedReaderDemo {
	public static void sop(Object obj){
		System.out.println(obj);
	}
	public static void main(String[] args) {
		method();
	}
	public static void method(){
		FileReader fr = null;
		BufferedReader bufr = null;
		try{
			fr = new FileReader("buf.txt");//初始化读取流对象。
			bufr = new BufferedReader(fr);//将字符流读取对象作为参数传递给缓冲对象的构造函数。
			String line = null;
			while((line = bufr.readLine()) != null)
				sop("(readLine)" + line);
		}catch(IOException e){
			throw new RuntimeException("写入失败");
		}finally{
			try{
				if (bufr != null)
					bufr.close();
			}catch(IOException e){
				throw new RuntimeException("写入关闭失败");
			}
		}
	}
}
运行结果如下图所示:


03)通过缓冲区复制文本文件

/*
 * 通过通过缓冲区复制文本文件:
 * BufferedReader。
 * BufferedWriter。
 */
public class ReadLineDemo_copy {
	public static void sop(Object obj){
		System.out.println(obj);
	}
	public static void main(String[] args) {
		method();
	}
	public static void method(){
		BufferedReader bufr = null;
		BufferedWriter bufw = null;
		try{
			bufr = new BufferedReader(new FileReader("RuntimeDemo.java"));
			bufw = new BufferedWriter(new FileWriter("BufferedWriter_copy.txt"));
			String line = null;//相当于中转站。
			while((line = bufr.readLine()) != null){
				bufw.write(line);
				bufw.newLine();//换行。
			}
		}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) {
				sop("写入关闭失败");
			}
		}
	}
}
运行结果如下图所示:


05)模拟BufferedReader

/*
 * 模拟BufferedReader。
 * 通过自定义一个类中包含一个功能和readLine一致的方法。
 */
public class MyBufferedReaderDemo {
	public static void main(String[] args) {
		method();
	}
	
	public static void method(){
		MyBufferedReader mybufr = null;
		try{
			mybufr = new MyBufferedReader(new FileReader("buf.txt"));
			String line = null;
			while((line = mybufr.myReadLine()) != null)
				System.out.println(line);
		}catch(IOException e){
			e.printStackTrace();
		}finally{
			if (mybufr != null)
				try{
					mybufr.myClose();
				}catch(IOException e){
					e.printStackTrace();
				}
		}
	}
}
class MyBufferedReader{
	private Reader r;
	MyBufferedReader(Reader r){
		this.r = r;
	}
	public String myReadLine() throws IOException{//可以一次读一行数据的方法。
		//定义一个临时容器(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();
	}
}
运行结果如下图所示:


06)装饰设计模式

/*
 * 装饰设计模式:
 * 当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有对象的功能,并提供加强功能
 * 那么自定义的该类称为装饰类。
 * 
 * 特点:装饰类通常会通过构造方法接受被装饰的对象。并基于被装饰对象的功能,提供更强的功能。
 */
public class PersonDemo {
	public static void main(String[] args) {
		method();
	}
	public static void method(){
		SuperPerson sp = new SuperPerson(new Person());
		sp.superchifan();
	}
}

class Person{
	public void chifan(){//需要被增强的功能。
		System.out.println("吃饭!");
	}
}

class SuperPerson{//装饰类。
	private Person p;
	SuperPerson(Person p){
		this.p = p;
	}
	public void superchifan(){//增强功能。
		sop("开胃酒!");
		p.chifan();
		sop("甜点!");
		sop("来一把!");
	}
	public void sop(Object obj){
		System.out.println(obj);
	}
}
运行结果如下图所示:


07)装饰和继承的区别

/*
 * 装饰模式比继承要灵活。避免了继承体系臃肿。
 * 而且降低了类于类之间的关系。
 * 
 * 装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。
 * 所以装饰类和被装饰类通常是都属于一个体系中的。
 */
/*
 * MyReader//专门用于读取数据的类。
 * 	|--MyTextReader
 * 		|--MyBufferTextReader
 * 	|--MyMediaReader
 * 		|--MyBufferMediaReader
 * 	|--MyDataReader
 * 		|--MyBufferDataReader
 * 
 * class MyBufferReader{
 * 		MyBufferReader(MyTextReader text){
 * 		}
 * 		MyBufferReader(MyMediaReader media){
 * 		}
 * }
 * 上面这个类扩展性很差。
 * 找到其参数的共同类型。通过多态的形式。可以提高扩展性。
 * 
 * class MyBufferReader extends MyReader{
 * 		private MyReader r;
 * 		MyBufferReader(MyReader r){
 * 		}
 * }	
 * 
 * MyReader//专门用于读取数据的类。
 * 	|--MyTextReader
 * 	|--MyMediaReader
 * 	|--MyDataReader
 * 	|--MyBufferReader
 * 
 * 以前是通过继承将每一个子类都具备缓冲功能。
 * 那么继承体系会复杂,并不利于扩展。
 * 
 * 现在优化思想。单独描述一下缓冲内容。
 * 将需要被缓冲的对象。传递进来。也就是,谁需要被缓冲,谁就作为参数传递给缓冲区。
 * 这样继承体系就变得很简单。优化了体系结构。
 * 
 * 装饰模式比继承要灵活。避免了继承体系臃肿。
 * 而且降低了类于类之间的关系。
 * 
 * 装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。
 * 所以装饰类和被装饰类通常是都属于一个体系中的。
 */

08)自定义装饰类

/*
 * 自定义装饰类继承Reader类,就需要实现Reader类的所有抽象方法。
 * close()与read(char[] cbuf, int off, int len)方法。
 */
class MyBufferedReader_2 extends Reader{//继承Reader类,所以需要实现Reader类的抽象方法。
	private Reader r;
	MyBufferedReader_2(Reader r){
		this.r = r;
	}
	public String myReadLine() throws IOException{//可以一次读一行数据的方法。
		//定义一个临时容器(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 close() throws IOException{//实现抽象类。
		r.close();
	}
	public int read(char[] cbuf, int off, int len) throws IOException{//实现抽象类。
		return r.read(cbuf, off, len);
	}
	public void myClose() throws IOException{
		r.close();
	}
}

09)LineNumberReader

/*
 * LineNumberReader(Reader in):使用默认输入缓冲区的大小创建新的行编号 reader。 
 * int getLineNumber():获得当前行号。
 * void setLineNumber(int lineNumber):设置当前行号。
 */
public class LineNumberReaderDemo {
	public static void main(String[] args){
		method();
	}
	public static void method(){
		LineNumberReader lnr = null;
		try{
			lnr = new LineNumberReader(new FileReader("RuntimeDemo.java"));
			String line = null;
			lnr.setLineNumber(30);//设置起始标记值。
			while ((line = lnr.readLine()) != null)
				System.out.println(lnr.getLineNumber() + ":" + line);
		}catch(IOException e){
			throw new RuntimeException("系统找不到指定的文件");
		}finally{
			if (lnr != null)
				try{
					lnr.close();
				}catch(IOException e){
				}
		}
	}
}
运行结果如下图所示:


10)MyLineNumberReader

/*
 * 自定义装饰类。
 * MyLineNumberReader类通过继承MyBufferedReader类以优化代码。
 */
public class MyLineNumberReaderDemo {
	public static void main(String[] args) {
		method();
	}
	public static void method(){
		LineNumberReader lnr = null;
		try{
			lnr = new LineNumberReader(new FileReader("RuntimeDemo.java"));
			String line = null;
			lnr.setLineNumber(10);//设置起始标记值。从(10+1)开始。
			while ((line = lnr.readLine()) != null)
				System.out.println(lnr.getLineNumber() + ":" + line);
		}catch(IOException e){
			throw new RuntimeException("系统找不到指定的文件");
		}finally{
			if (lnr != null)
				try{
					lnr.close();
				}catch(IOException e){
				}
		}
	}
}

class MyLineNumberReader extends MyBufferedReader{
	private int lineNumber;
	MyLineNumberReader(Reader r){
		super(r);
	}
	public String myReadLine() throws IOException{
		lineNumber++;
		return super.myReadLine();
	}
	public void setLineNumber(int lineNumber){
		this.lineNumber = lineNumber;
	}
	public int getLineNumber(){
		return lineNumber;
	}
}
运行结果如下图所示:


11)字节流File读写操作

/*
 * 字节流:
 * 读:InputStream 
 * 写:Output Stream
 * void write(byte[] b): 
 * 
 * 需求:操作图片数据。
 * 这时就需要用到字节流。
 */
public class FileStreamDemo {
	public static void main(String[] args) throws IOException{
		writerFile();
		readFile();
	}
	public static void readFile() throws IOException{
		FileInputStream fis = new FileInputStream("fos.txt");
		//注意:只有当读取的文件小于JVM提供的内存时,才使用下面这种方法。
		//当读取文件足够大时,会发生缓冲区溢出。
		byte[] byf = new byte[fis.available()];//定义一个刚刚好的字节数组。
		fis.read(byf);
		System.out.println(new String(byf));
		fis.close();
	}
	public static void writerFile(){
		FileOutputStream fos = null;
		try{
			fos = new FileOutputStream("fos.txt");
			fos.write("abcdefg".getBytes());
		}catch(IOException e){
			
		}finally{
			if (fos != null)
				try{
					fos.close();
				}catch(IOException e){
				}
		}
	}
}

12)拷贝图片

/*
 * 拷贝一张图片。
 * 思路:
 * 1:用字节读取流对象和图片关联。
 * 2:用字节写入流对象创建一个图片文件。用于存储获取到的图片数据。
 * 3:通过循环读写,完成数据的存储。
 * 4:关闭资源。
 */
public class CopyJpgDemo {
	public static void main(String[] args) {
		method();
	}
	public static void method(){
		FileOutputStream fos = null;
		FileInputStream fis = null;
		try{
			fos = new FileOutputStream("G:\\copy\\Java学习路线图.jpg");//目标图片文件。
			fis = new FileInputStream("G:\\copy\\Java学习.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("写入关闭失败");
			}
		}
	}
}

13)MP3的拷贝

/*
 * mp3的复制。通过缓冲区。
 * BufferedOutputStream
 * BufferedInputStream
 */
public class CopyMp3Demo {
	public static void main(String[] args) throws IOException{
		long start = System.currentTimeMillis();
		method();
		long end = System.currentTimeMillis();
		System.out.println("time = " + (end - start) + "毫秒");//看下拷贝这个mp3文件用时多久。
	}
	//通过字节流的缓冲区完成复制。
	public static void method() throws IOException{
		BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("G:\\copy\\一眼万年.mp3"));//源mp3文件。
		BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("G:\\copy\\二眼亿年.mp3"));//目标mp3文件。
		int by = 0;
		while((by = bufis.read()) != -1)
			bufos.write(by);
		bufos.close();
		bufis.close();
	}
}


15)读取键盘录入

/*
 * 读取键盘录入。
 * System.out:标准的输出设备,控制台。
 * System.in:标准的输入设备,键盘。
 * 
 * 需求:通过键盘录入数据:
 * 当录入一行数据后,就将该行数据打印(大写)。
 * 如果录入的数据是over,那么就停止录入。
 */
public class ReadInDemo {
	public static void sop(Object obj){
		System.out.println(obj);
	}
	public static void main(String[] args) throws IOException{
		method();
	}
	public static void method() throws IOException{
		InputStream in = System.in;
		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)){
					sop("结束了");
					break;
				}
				sop(s.toUpperCase());
				sb.delete(0, sb.length());
			}else
				sb.append((char)ch);
		}
	}
}

16)读取转换流

/*
 * 使用readLine方法来完成键盘录入一行数据的读取。
 * readLine是(字符流)BufferedReader类中的方法。
 * 而键盘录入read是(字节流)InputStream的方法。
 */
public class TransStreamDemo {
	public static void sop(Object obj){
		System.out.println(obj);
	}
	public static void main(String[] args) throws IOException{
		method();
	}
	public static void method() throws IOException{
		//获取键盘录入对象。
		InputStream in = System.in;
		//将字节流对象转换成字符流对象,使用转换流。
		InputStreamReader isr = new InputStreamReader(in);
		//为了提高效率,将字符串进行缓冲区技术高效操作。
		BufferedReader bufr = new BufferedReader(isr);
		String line = null;
		while((line = bufr.readLine()) != null){
			if ("over".equals(line)){
				sop("结束了!");
				break;
			}
			sop(line.toUpperCase());
		}
		in.close();
	}
}

17)写入流转换

/*
 * 键盘最常见写法。
 * BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
 */
public class TransStreamDemo_2 {
	public static void main(String[] args) throws IOException{
		method();
	}
	public static void method() throws IOException{
		//键盘最常见写法。
		BufferedReader bufr = 
				new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bufw = 
				new BufferedWriter(new OutputStreamWriter(System.out));
		
		String line = null;
		while ((line = bufr.readLine()) != null){
			if ("over".equals(line)){
				System.out.println("结束了");
				break;
			}
			bufw.write(line.toUpperCase());
			bufw.newLine();
			bufw.flush();
		}
		bufr.close();
	}
}

18)流操作规律

/*
 * 1:需求:将键盘录入的数据打印到控制台。
 * 源:键盘录入。(System.in)
 * 目的:控制台。(System.out)
 * 
 * 2:需求:将键盘录入的数据存储到文件中。
 * 源:键盘。(System.out)
 * 目的:文件。(FileOutputStream("文件名"))
 * 
 * 3:需求:将文件中的数据打印到控制台。
 * 源:文件。(FileInputStream("文件名"))
 * 目的:控制台。(System.out)
 * 
 * 流操作的基本规律:(非常重要)
 * 疑惑:流对象有很多,但不知道该用哪一个。
 * 通过三个明确:
 * 1:明确(源)和(目的)。
 * 		源:输入流。(InputStream)(Reader)
 * 		目的:流出流。(OutputStream)(Writer)
 * 2:明确操作的数据是否是(纯文本)。
 * 		是:字符流。
 * 		否:字节流。
 * 3:当体系明确后,再明确要使用哪个具体的对象。
 * 		通过设备来进行区分:
 * 			源设备:内存,硬盘(文件),键盘。(FileReader)
 * 			目的设备:内存,硬盘(文件),控制台。(FileWriter)
 * 
 * 提高效率:
 * 	源:(BufferedReader)
 * 	目的:(BufferedWriter)
 * 	
 */


附言:我是Java新人,如有错误的地方请指出。
                         每天学习一点点,纠错一点点,进步很大点。

-------  android培训java培训java学习型技术博客、期待与您交流! ----------


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值