Java IO (五) 之 处理流和装饰流

处理流

引入1_模拟方法器对人的声音的放大

package com.sxt.IO_01;

public class Decorate {

	/**
	 *@描述:
	 * @param args
	 */
	public static void main(String[] args) {
		Person p = new Person();
		p.say();
		Amplify amplify = new Amplify(p);
		amplify.say();
	}
}
/**
 * 
 * @描述:定义接口
 */
interface Say{
	void say();
}
/**
 * 
 * @描述:定义人并实现承接口
 */
class Person implements Say{
	int voice = 10;
	@Override
	public void say() {
		System.out.println("原来声音大小为:"+this.voice);
	}
}
/**
 * 
 * @描述:定义放大器并继承接口对声音进行放大
 */
class Amplify implements Say{
	private Person p;
	public Amplify(Person p) {
		this.p = p;
	}

	@Override
	public void say() {
		System.out.println("放大后的声音为:"+p.voice * 1000);
	}
}

引入2_模拟咖啡加料

package com.sxt.IO_01;
/**
 * 1、抽象组件(饮料):需要装饰的抽象对象(是接口或抽象父类)
 * 2、具体组件(咖啡):需要装饰的对象
 * 3、抽象装饰类:包含了对抽象组件的引用以及装饰类所共有的方法
 * 4、具体装饰类:被装饰的对象
 * @描述:模拟咖啡
 */
public class Decorate_Coffe {
	public static void main(String[] args) {
		Drink coffee = new Coffee();
		System.out.println("价格:"+coffee.cost());
		System.out.println("信息:"+coffee.info());
		Drink milk = new Milk(coffee);
		System.out.println("---------------");
		System.out.println("价格:"+milk.cost());
		System.out.println("信息:"+milk.info());
		System.out.println("------------------");
		Drink suger = new Suger(coffee);
		System.out.println("---------------");
		System.out.println("价格:"+suger.cost());
		System.out.println("信息:"+suger.info());
	}
}
//1、抽象组件
interface Drink{
	//费用
	double cost();
	//说明
	String info();
}
//2、具体组件
class Coffee implements Drink{
	double price = 1;
	String name ="原味咖啡";
	@Override
	public double cost() {
		return price;
	}

	@Override
	public String info() {
		return name;
	}
	
}
//3、抽象装饰类
abstract class Decorate implements Drink{
	//对抽象组件的引用
	Drink drink;
	protected Decorate(Drink drink) {
		this.drink = drink;
	}

	@Override
	public double cost() {
		return this.drink.cost();
	}

	@Override
	public String info() {
		return this.drink.info();
	}
	
}
//4、具体装饰类
//4_1装饰类1
class Milk extends Decorate{

	Milk(Drink drink) {
		super(drink);
	}
	@Override
	public double cost() {
		return super.cost()*4;
	}
	@Override
	public String info() {
		return super.info()+"加入了牛奶";
	} 
}
//4_2、装饰类2
class Suger extends Decorate{

	Suger(Drink drink) {
		super(drink);
	}
	@Override
	public double cost() {
		return super.cost()*2;
	}
	@Override
	public String info() {
		return super.info()+"加入了糖";
	} 
}

装饰流

引入:由于Io的操作直接影响着程序性能高低。

  • 一件一件的搬家(蚂蚁搬家)
  • 一卡车一卡车的搬家(搬家公司搬家)
  • 将物品打包(多个包)然后直接一次性的搬走(打包,不需要频繁的对硬盘进行操作)

字节缓冲流

作用:

  1. 提高了字节数据读写的性能。
  2. 任何的处理流最底层的都是节点流
  3. 流的释放只需要释放最外层的处理流(因为它的内部会自动释放内部的节点流)

区别:在节点流的外面套上字节缓冲流即可,其他操作不变

利用字节缓冲输入流来读取数据

package com.sxt.IO_03;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class bufferInputStrea {
	public static void main(String[] args) {
		//1.创建源
		File file = new File("des.txt");
		//2.选择流
		InputStream in = null;
		try {
			in = new BufferedInputStream(new FileInputStream(file));
			//3.操作(读取数据)
			byte[] flush = new byte[1024];
			//接收长度
			int len = -1;
			try {
				while((len = in.read(flush)) != -1){
					//字节数组-->字符串(解码)
					String str = new String(flush,0,len);
					System.out.print(str);
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}finally{
			if(in != null){
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

字符缓冲流

注意:

  1. 在使用字符缓冲流的时候尽量不使用多态,因为相对于它的父类它自己本身新增的方法更为常用
  2. 在节点流的外面套上字符缓冲流就可以

利用字符缓冲输入流来读取数据

package com.sxt.IO_03;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class bufferReader {
	public static void main(String[] args) {
		//创建源
		File file = new File("hello.txt");
		//选择流
		BufferedReader reader = null;
		try {
			reader = new BufferedReader(new FileReader(file));
			//读取数据(操作):当读取的数据不存在时返回null,读取的数据存放在line中
			String line;
			while((line = reader.readLine())!= null){
				System.out.println(line);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			//关闭资源
			try {
				if(reader != null){
					reader.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
}

利用字符缓冲输出流来写入数据

注意:这里使用到了BufferedWriter特有的换行方法

package com.sxt.IO_03;

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

public class bufferWriter {

	/**
	 *@描述:
	 * @param args
	 */
	public static void main(String[] args) {
		//1.准备源
		File des = new File("src2/com/sxt/IO_03/des1.txt");
		//2.选择字符输出流
		BufferedWriter writer = null;
		try {
			 writer = new BufferedWriter(new FileWriter(des));
		} catch (IOException e) {
			e.printStackTrace();
		}
		//3.读取操作
		//3.1准备要写出的数据
		String data = "我能行!加油!";
		//3.2准备小车
		char[] flush = new char[1024];
		//3.3将数据放进小车中
		flush = data.toCharArray();
		try {
			//3.3读取操作
			writer.write(flush);
			//BufferedWriter特有的换行方法
			writer.newLine();
			writer.append("嗯,是的就是这样的!");
			//3.4flush操作
			writer.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if(writer != null){
				try {
					writer.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

利用字符缓冲流来进行文件之间的复制

注意:

  1. 逐行读取数据
  2. 将数据逐行写出
  3. 换行输出
package com.sxt.IO_03;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.Closeable;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class bufferReader_Writer_copy {
	public static void main(String[] args) {
		//1.准备源
		File src = new File("src.txt");
		File des = new File("src2/com/sxt/IO_03/des3.txt");
		//2.选择流
		BufferedReader reader = null;
		BufferedWriter writer = null;
		try {
			 reader = new BufferedReader(new FileReader(src));
			 writer = new BufferedWriter(new FileWriter(des));
		//3.逐行读取数据
			String line;
			while((line = reader.readLine())!= null){
                //将数据逐行写出
				writer.write(line);
                //换行输出
				writer.newLine();
				writer.flush();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			//4.关闭
			close(reader,writer);
			
		}
	}
	public static void close(Closeable ... clos){
		for(Closeable clo : clos){
			if(clo != null){
				try {
					clo.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

转换流

InputStreamReader和OutputStreamWriter是字节流和字符流之间的桥梁,可以将字节流转换为字符流,并可以为字节流指定字符集,可以处理一个一个的字符

转化流

作用:

  1. 作为字节流和字符流的桥梁,以字符流的形式操作字节流(纯文本)
  2. 分别具有解码和编码的作用
  • InputStreamReader是从字节流到字符流的桥:它读取字节,并使用指定的charset将其解码为字符(解码)
  • OutputStreamWriter是字符流到字节流的桥梁:向其写入的字符编码成使用指定的字节charset (编码)

作用1:以字符流的形式操作字节流(纯文本)

注意:

  1. 涉及到字符数据的操作,可以加一个字符缓冲流来提高效率
  2. 在对数据进行写入完成要记得强制刷新,否则控制台可能不会显示输入的数据
package com.sxt.IO_03;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class Convert {
	public static void main(String[] args) {
//		//操作System.in(字节输入流)和System.out(字节输出流)
//		InputStreamReader in = new InputStreamReader(System.in);
//		OutputStreamWriter out = new OutputStreamWriter(System.out);
		//由于这里读取和写出操作的都是字符,因此加了一个缓冲来提高效率
		//字节输入流--字符输入流--修饰缓冲
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		//字节输出流--字符输出流--修饰缓冲
		BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
		//2、循环获取键盘的输入(遇到exit退出循环),打印此内容
		String mes = "";
		while(!mes.equals("exit")){
			try {
				//逐行读取数据
				mes = reader.readLine();
				//逐行对数据进行写人
				writer.write(mes);
				writer.newLine();
				//对缓冲区进行强制刷新
				writer.flush();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}	
	}
}

作用2:指定字符集

package com.sxt.IO_03;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;

public class Convert1 {

	/**
	 * 作用2:指定字符集编码
	 *@描述:转换流
	 * @param args
	 */
	public static void main(String[] args) {
		//操作网络流(字节节点流),下载百度源码
		try {BufferedReader reader = 
			new BufferedReader(
				new InputStreamReader(
					new URL("http://www.baidu.com").openStream(),"UTF-8"));
		//对数据进行读取操作
		String mes = "";
		while((mes = reader.readLine())!= null){
			System.out.print(mes);
		}
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

数据流

dataOutputStream()

dataInputStream()

注意:

  1. 先写出后读取
  2. 读取的数据类型要和写入的数据类型一致
package com.sxt.IO_03;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class dataIO {

	/**
	 *@描述:
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		//1.数据的写入
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		DataOutputStream dos = new DataOutputStream(
				new BufferedOutputStream(bos));
		dos.writeUTF("张三");
		dos.writeInt(24);
		dos.writeChar('男');
		//注意数据在写入之后要记得flush,否则会出现异常
		dos.flush();
		//2.数据的读取
		byte[] datas = bos.toByteArray();
		ByteArrayInputStream bis = new ByteArrayInputStream(datas);
		DataInputStream dis = new DataInputStream(
				new BufferedInputStream(bis));
		String name = dis.readUTF();
		int age = dis.readInt();
		char sex = dis.readChar();
		System.out.println(name + age + sex);
	}

}

对象流

注意:

  1. 先写出后读取
  2. 读取的顺序和写出的顺序一致
  3. 不是所有的对象都可以序列化(必须实现一个接口Serializable)

序列化:ObjectOutputStream:只有支持serializable接口的对象才能写入流中。(编写的原始数据和对象。)

反序列化:ObjectInputStream:只能从流中读取支持java.io.serializable或java.io.externalizable接口的对象

package com.sxt.IO_03;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.Date;

public class objectIO {

	/**
	 *@描述:对象流
	 * @param args
	 * @throws IOException 
	 * @throws ClassNotFoundException 
	 */
	public static void main(String[] args) throws IOException, ClassNotFoundException {
		//1.数据的写入
		OutputStream os = new FileOutputStream("src2/com/sxt/IO_03/des.txt");
		ObjectOutputStream oos = new ObjectOutputStream(
				new BufferedOutputStream(os));
		oos.writeObject("哈哈,每天都是那么的美好!");
		oos.writeObject(new Person("张三",19));
		oos.writeObject(new Date());
		oos.flush();
		oos.close();
		//2.数据的读取
		InputStream is = new FileInputStream("src2/com/sxt/IO_03/des.txt");
		ObjectInputStream ois = new ObjectInputStream(
				new BufferedInputStream(is));
		Object info = ois.readObject();
		Object personInfo = ois.readObject();
		Object date = ois.readObject();
		if(info instanceof String){
			String info1 = (String)info;
			System.out.println(info1);
		}
		if(personInfo instanceof Person){
			Person personStrInfo1 = (Person)personInfo;
			System.out.println(personStrInfo1);
		}
		if(date instanceof Date){
			Date date1 = (Date)date;
			System.out.println(date1);
		}
	}
}
class Person implements Serializable{
	//表示该数据不需要被序列化
	transient String name;
	int age;
	Person(String name, int age){
		this.name = name;
		this.age = age;
	}
	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return name+":" +age;
	}
}

打印流

要知道的:System类

  1. System类包含几个有用的类字段和方法。 它不能被实例化。
  2. System类提供的System包括标准输入,标准输出和错误输出流;
    • 返回类型方法和描述
      static PrintStreamerr “标准”错误输出流。
      static InputStreamin “标准”输入流。
      static PrintStreamout “标准”输出流。

    printStream练习

package com.sxt.IO_03;
import java.io.BufferedOutputStream;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;

public class printStream_demon {

	/**
	 *@描述:打印流PrintStream
	 * @param args
	 * @throws FileNotFoundException 
	 */
	public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
		PrintStream ps = System.out;
		ps.println("第一次被打印(在控制台中显示打印内容)");
		//PrintStream(OutputStream out, boolean autoFlush) 将内容打印到文件中
		//(注意要"自动刷新,否则打印的内容可能会不显示")
		ps = new PrintStream(
				new BufferedOutputStream(
						new FileOutputStream("src2/com/sxt/IO_03/printText.txt")),true);
		ps.println("第二次被打印了(在指定文件中被显示打印内容)");
		//重定向到输出端
		//static void setOut(PrintStream out) 重新分配“标准”输出流。  
		System.setOut(ps);
		System.out.println("第三次被打印(打印内容给指定的输出端)");
		//重定向到控制台(注意要"自动刷新,否则打印的内容可能会不显示")
		System.setOut(
				new PrintStream(
						new BufferedOutputStream(
								new FileOutputStream(FileDescriptor.out)),true));
		System.out.println("第四被打印(打印的东西给控制台显示)");
		ps.close();
	}

}

printStream练习

package com.sxt.IO_03;

import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;

public class printWriter_demon {

	/**
	 *@描述:PrinrWriter
	 * @param args
	 * @throws FileNotFoundException 
	 */
	public static void main(String[] args) throws FileNotFoundException {
		PrintWriter pw = new PrintWriter(
				new BufferedOutputStream(
						new FileOutputStream("src2/com/sxt/IO_03/printText01.txt")),true);
		pw.println("被打印在指定文件中了");
	}

}

随机访问

RandomAccessFile

package com.sxt.IO_03;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

public class randomAccessFile_Demon {

	/**
	 *@描述:
	 *void seek(long pos) 设置文件指针偏移,从该文件的开头测量,
	 *发生下一次读取或写入。  
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		//1.指定要分隔的文件
		File file = new File("src2/com/sxt/IO_03/RandomText.txt");
		//确定文件的长度
		long len = file.length();
		System.out.println(len);
		//确定每块的大小
		int blockSize = 100;
		//一共分隔的块数
		int blockNum = (int)(Math.ceil((len*1.0)/blockSize));
		System.out.println(blockNum);
		//每次读取的起始位置
		int beginPos = 0;
		//每次分配块的实际大小
		int actualSize = (int)(blockSize > len ? len:blockSize);
		for(int i = 1; i <= blockNum; i++){
			beginPos = i * blockSize;
			if(i == blockNum){//最后一块(可能装不满)
				actualSize = (int) len;
			}else{
				actualSize = blockSize;
				len -= actualSize;
			}
			System.out.println(i +"块---> 起始位置:" 
			+ beginPos + "----> 实际读取块的大小:"
			+actualSize);
		}
	}
	/**
	 * 
	 *@描述:按照分块的形式对数据进行读取
	 * @throws IOException
	 */
	public static void RandomRead1() throws IOException{
		RandomAccessFile raf = new RandomAccessFile(
				new File("src2/com/sxt/IO_03/RandomText.txt"),"r");
		//分块读取数据:
		//起始位置
		int beginPos = 4;
		//实际需要读取数据的大小
		int actualSize = 106;
		//开始读取数据
		int len = -1;
		byte[] flush = new byte[1024];
		raf.seek(beginPos);
		while((len = raf.read(flush)) != -1){
			if(len < actualSize){//获取本次读取的所有内容
				raf.read(flush);
				actualSize -= len;
				System.out.println(new String(flush));
			}else{
				raf.read(flush,0,actualSize);
				System.out.println(new String(flush,0,actualSize));
				
			}
		}
		raf.close();
	}
	/**
	 * 
	 *@描述:指定起始读取位置,读取剩余所有内容;
	 * @throws IOException
	 */
	public static void RandomRead() throws IOException{
		RandomAccessFile raf = new RandomAccessFile(
				new File("src2/com/sxt/IO_03/RandomText.txt"),"r");
		//开始读取数据
		byte[] flush = new byte[1024];
		int len= -1;
		raf.seek(2);
		while((len = raf.read(flush))!= -1){
			System.out.println(new String(flush,0,len));
		}
		raf.close();
	}

}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值