019.day19 缓冲流 对象流 标准输入输出流

缓冲流和对象流

本节任务

缓冲流

对象流

标准输入输出流

教学目标

掌握缓冲流的用法

掌握序列化和反序列化

掌握标准输入输出流的用法

教学内容

一、缓冲流

主要为了提高读写效率,增强基础流的功能

  • 实例化File对象
  • 实例化缓冲流对象,需要基础流作为参数

1. 缓冲输入流

(1)BufferedInputStream
// TODO 字符缓冲输入流BufferedReader
		// 1.实例化一个BufferedReader
		// 默认缓冲区大小:8192,当标记中指定的记录的字符数小于缓冲数组剩余长度时,不会发生异常
		// 当缓冲数组足够大时,该标记一直会保留到当前缓冲数组装满
		Reader reader = new BufferedReader(new FileReader(new File("f:/test.txt")),5);
		// 2.BufferedReader中支持mark和reset
		String result = "";
		// 3.使用mark进行标记
		result += (char)reader.read();
		result += (char)reader.read();
		result += (char)reader.read();
		result += (char)reader.read();
		// mark当中参数的作用:再读取多少个字符之后,标记点失效
		reader.mark(3);
		// 4.使用reset方法返回标记的位置
		result += (char)reader.read();
		result += (char)reader.read();
		result += (char)reader.read();
		// 失效:limit -> 要求记录的字符数 -> 失效条件:读取的字符总数会超出缓冲区大小
		// 当需要记录的字符刚好超出了当前缓冲区,会在下一个缓冲区中继续存放,直到下一个缓冲区存满,标记失效
		reader.reset();
		result += (char)reader.read();
		result += (char)reader.read();
		result += (char)reader.read();
		System.out.println(result);
		reader.close();
  • mark(int marklimit):标记位置
  • reset():如果可能,回到标记位置
// TODO 缓冲流-标记和重置练习
		// 在文本文件中指定一对特殊字符(能够被唯一识别的)
		// 当读取到第一个特殊字符时,标记当前位置
		// 当读取到第二个特殊字符时,重置,继续读取完所有文件内容
		Reader reader = new BufferedReader(new FileReader(new File("f:/test.txt")));
		int i = 0;
		int count = 1;
		String result = "";
		while ((i = reader.read()) != -1) {
			if ('!' == (char)i && count == 1) {
				reader.mark(30);
				count ++;
			}else if('!' == (char)i && count == 2) {
				reader.reset();
				count ++;
			}
			result += (char)i;
		}
		System.out.println(result);
		reader.close();
(2)BufferedReader
  • readLine():直接读取一行
// TODO 字符缓冲流 - 每次读取一行 - 读取文件中所有内容
		// 1.初始化缓冲流
		BufferedReader bufferedReader = new BufferedReader(new FileReader(new File("E:/test.txt")));
		String line = "";
		// 2.读取文件内容
		while ((line = bufferedReader.readLine()) != null) {
			// 读取的内容本身不包括换行符
			System.out.println(line);
		}
		// 3.关闭流
		bufferedReader.close();
  • 小练习

    // TODO 从文件中读取所有数据 - 单词计数
    		// 1.数据采集 - 数据来源:文本文件
    		// (1)指定文件路径
    		// 使用File类指定数据文件路径
    		File dataFile = new File("E:/data.txt");
    		// 使用dataFile初始化一个输入流
    		Reader fileReader = new FileReader(dataFile);
    		// 使用fileReader初始化一个缓冲流
    		BufferedReader bufferedReader = new BufferedReader(fileReader);
    		// (2)使用缓冲流一次读取一行
    		// 定义一个集合,存储读取到的数据
    		List<String> lines = new ArrayList<>();
    		// 定义字符串变量,接收每次读取的一行数据
    		String temp = "";
    		// (3)将获取到的数据存放到集合当中
    		while ((temp = bufferedReader.readLine()) != null) {
    			lines.add(temp);
    		}
    		// (4)关闭流 -> 关闭顺序与打开顺序相反
    		bufferedReader.close();
    		fileReader.close();
    		// 2.数据清洗 - 去除重复、缺失、偏差较大的数据
    		// 3.数据分析 - 统计计数
    		Map<String, Integer> result = new HashMap<>();
    		// (1)从集合中获取到每一行数据
    		for (String line : lines) {
    			// (2)根据相应的分隔符取出每一个单词作为待统计数据
    			String[] words = line.split(" ");
    			for (String word : words) {
    				// (3)当某一个单词第一次出现时,记为1
    				// (4)当某一个单词再次出现时,将出现的次数累加
    				// 第一次出现该单词
    				if (!result.containsKey(word)) {
    					result.put(word, 1);
    				}else {
    					// 取出当前单词已经出现的次数
    					int count = result.get(word);
    					result.put(word, count + 1);
    				}
    			}
    		}
    		// (5)重复以上步骤,直到遍历结束
    		// 4.结果打印
    		for (Map.Entry<String, Integer> string : result.entrySet()) {
    			System.out.println(string);
    		}
    

2. 缓冲输出流

(1)BufferedOutputStream
(2)BufferedWriter
  • newLine():写入一个行分隔符

二、对象流

如果流中流动的数据是对象则可称为对象流

  • 序列化:将一个对象写入到本地文件中
  • 反序列化:将一个本地文本文件中的对象读取出来
  • 一个对象流只能操作一个对象
  • 当需要同时序列化多个对象时,可以使用集合
// TODO 对象流
		// 输出流 -> 序列化过程 : 将当前对象当中包含的信息(状态) -> 保存至文件当中
		// 1-1.初始化对象输出流 -> 需要的参数 : 通用的输出流 -> FileOutputStream -> File -> 路径
		ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(new File("E:/shop.txt")));
		// 输入流 -> 反序列化过程 : 将文件当中存放的对象的信息 -> 返回一个对象(数据)
		// 1-2.初始化对象输入流 -> 需要的参数 : 通用的输入流 -> FileInputStream -> File -> 路径
		ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(new File("E:/shop.txt")));
		// 2.获得一个自定义类的实例
		Shop shop = new Shop("百货商厦");
		// 3-1.序列化对象 - 自定义类实现序列化接口 - ID根据需要进行生成
		outputStream.writeObject(shop);
		// 3-2.反序列化 - 判断类型 - 强制转换接收
		Object object = inputStream.readObject();
		// 如果反序列化得到的对象是相应的实例
		if (object instanceof Shop) {
			// 检查是否成功反序列化
			Shop newShop = (Shop)object;
			System.out.println(newShop);
		}
		// 4.强制刷新
		outputStream.flush();
		// 5.关闭流
		inputStream.close();
		outputStream.close();
//Product类中有引用数据类型变量Shop
// TODO 对象流应用 - 对象的深度克隆
		// 输出流 -> 序列化过程 : 将当前对象当中包含的信息(状态) -> 保存至文件当中
		// 1-1.初始化对象输出流 -> 需要的参数 : 通用的输出流 -> FileOutputStream -> File -> 路径
		ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(new File("E:/product.txt")));
		// 输入流 -> 反序列化过程 : 将文件当中存放的对象的信息 -> 返回一个对象(数据)
		// 1-2.初始化对象输入流 -> 需要的参数 : 通用的输入流 -> FileInputStream -> File -> 路径
		ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(new File("E:/product.txt")));
		// 2.获得一个自定义类的实例
		Product oldProduct = new Product("商品1", 200, new Shop("商店1"));
		// 3-1.序列化对象 - 自定义类实现序列化接口 - ID根据需要进行生成
		outputStream.writeObject(oldProduct);
		// 3-2.反序列化 - 判断类型 - 强制转换接收
		Object object = inputStream.readObject();
		// 如果反序列化得到的对象是相应的实例
		if (object instanceof Product) {
			// 检查是否成功反序列化
			Product newProduct = (Product) object;
			System.out.println(oldProduct);
			System.out.println(newProduct);
			oldProduct.setName("商品11");
			newProduct.setName("商品2");
			newProduct.getShop().setName("商店2");
			System.out.println(oldProduct);
			System.out.println(newProduct);
		}
		// 4.强制刷新
		outputStream.flush();
		// 5.关闭流
		inputStream.close();
		outputStream.close();
public class Product implements Serializable {

	public Product() {
		
	}

	public Product(String name, Integer price) {
		this.name = name;
		this.price = price;
	}
	
	public Product(String name, Integer price, Shop shop) {
		this.name = name;
		this.price = price;
		this.shop = shop;
	}

	private String name;
	// 封装类型比较时注意缓存机制以及手动拆箱
	private Integer price;
	// 成员变量中出现自定义类型,实例是一个引用类型
	private Shop shop;

	public Shop getShop() {
		return shop;
	}

	public void setShop(Shop shop) {
		this.shop = shop;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getPrice() {
		return price;
	}

	public void setPrice(Integer price) {
		this.price = price;
	}

	@Override
	public String toString() {
		return "Product [name=" + name + ", price=" + price + ", shop=" + shop + "]";
	}
public class Shop implements Serializable {
	
	private static final long serialVersionUID = -9099382180185766414L;

	public Shop() {

	}

	public Shop(String name) {
		this.name = name;
	}

	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Shop [name=" + name + "]";
	}
	
}

1. 序列化

  • ObjectOutputStream
  • writeObject(Object obj):将对象写入流中

2. 反序列化

  • ObjectInputStream
  • readObject():从流中读取对象
// TODO 对象流应用 - 对象的深度克隆
		// 输出流 -> 序列化过程 : 将当前对象当中包含的信息(状态) -> 保存至文件当中
		// 1-1.初始化对象输出流 -> 需要的参数 : 通用的输出流 -> FileOutputStream -> File -> 路径
		ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(new File("E:/product.txt")));
		// 输入流 -> 反序列化过程 : 将文件当中存放的对象的信息 -> 返回一个对象(数据)
		// 1-2.初始化对象输入流 -> 需要的参数 : 通用的输入流 -> FileInputStream -> File -> 路径
		ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(new File("E:/product.txt")));
		// 2.获得一个自定义类的实例
		Product oldProduct = new Product("商品1", 200, new Shop("商店1"));
		// 3-1.序列化对象 - 自定义类实现序列化接口 - ID根据需要进行生成
		outputStream.writeObject(oldProduct);
		// 3-2.反序列化 - 判断类型 - 强制转换接收
		Object object = inputStream.readObject();
		// 如果反序列化得到的对象是相应的实例
		if (object instanceof Product) {
			// 检查是否成功反序列化
			Product newProduct = (Product) object;
			System.out.println(oldProduct);
			System.out.println(newProduct);
			oldProduct.setName("商品11");
			newProduct.setName("商品2");
			newProduct.getShop().setName("商店2");
			System.out.println(oldProduct);
			System.out.println(newProduct);
		}
		// 4.强制刷新
		outputStream.flush();
		// 5.关闭流
		inputStream.close();
		outputStream.close();

三、标准输入输出流

标准输入输出流是System.in和System.out,默认情况下代表键盘和显示器

1. 输出流

  • PrintStream
  • setOut(PrintStream out):重新分配标准输出流
// TODO 标准的输出流
		PrintStream out = System.out;
		System.out.println("123");
		OutputStream outputStream = new FileOutputStream("E:/SystemTest.txt");
		// 自定义输出路径 默认屏幕上
		System.setOut(new PrintStream(outputStream));
		System.out.println("456");
		System.setOut(out);
		System.out.println(456);

2. 输入流

  • setIn(InputStream in):重新分配标准输入流
// TODO 标准的输入流
		InputStream in = System.in;
		InputStream inputStream = new FileInputStream(new File("E:/SystemTest.txt"));
		System.setIn(inputStream);
		Scanner scanner = new Scanner(System.in);
		// 使用Scanner实现文件内容读取
		while (scanner.hasNext()) {
			System.out.println(scanner.nextLine());
		}
		System.setIn(in);
		scanner = new Scanner(System.in);
		scanner.nextLine();
		scanner.close();
  • 小练习
// TODO 标准流练习
		// 从键盘录入一组数据(字符串)
		PrintStream out = System.out;
		// (1)使用默认的标准输入流初始化一个Scanner对象
		Scanner scanner = new Scanner(System.in);
		// (2)定义一个集合用于存放接收到的字符串
		List<String> list = new ArrayList<>();
		int n = 4;
		System.out.println("请输入四条数据:");
		for(int i = 0;i < n;i ++) {
			list.add(scanner.nextLine());
		}
		// 使用标准输出流写入到文件中
		// (1)定义一个文件输出流 -> 指定到某一个文件
		OutputStream outputStream = new FileOutputStream(new File("E:/SystemTest.txt"));
		// (2)改变标准输出流的指向 -> 文件输出流
		System.setOut(new PrintStream(outputStream));
		// (3)遍历集合,使用println()方法输出集合元素
		for (String line : list) {
			System.out.println(line);
		}
		// 利用标准输入流实现使用Scanner读取文件中的内容,打印输出
		// (1)定义一个文件输入流 -> 指定到数据记录文件
		InputStream inputStream = new FileInputStream(new File("E:/SystemTest.txt"));
		// (2)改变标准输入流的指向 -> 文件输入流
		System.setIn(inputStream);
		// (3)使用改变后的标准输入流初始化一个新的Scanner对象
		scanner = new Scanner(System.in);
		// (4)重置标准输出流 -> 显示器
		System.setOut(out);
		// (5)使用Scanner对象的nextLine()方法读取数据
		while (scanner.hasNext()) {
			System.out.println(scanner.nextLine());
		}
		scanner.close();
原文地址:https://www.cnblogs.com/yokii/p/9441913.html