Java IO流——标准IO重新包装、重定向、对象序列化

目录

前言

标准I/O

重新包装标准I/O

标准I/O流重定向

对象的序列化和反序列化

JDK类库中的序列化API

最后


前言

在上两篇文章中,我们学习了Java I/O流——面向字节的输入/输出流面向字符的输入/输出流,今天,我们学习Java I/O流——标准I/O、重新包装标准I/O、标准I/O流重定向、对象序列化。

标准I/O

输入流和输出流对象的生命周期是短暂的,不会存在于程序运行的整个生命周期,通常在I/O操作完毕时就应该适时地关闭I/O流。但有些应用程序需要在程序运行的整个生命周期中,例如日志文件。若每次都要重新打开I/O流,再关闭,会很不方便,因此,java.lang.System类提供以下3个静态常量:

  • static final InputStream in :标准输入流,已打开并准备提供输入数据,从键盘输入或主机或用户指定的另一个输入源;

  • static final PrintStream out :标准输出流,已打开并准备接收输出数据,从显示器输出或由主机或用户指定的另一个输出目标;;

  • static final PrintStream err :标准错误输出流,已打开并准备接收输出错误信息,从显示器输出或者由主机或用户指定的另一个输出目标。

以上3个流由JVM在启动程序时自动创建,它们存在程序运行的整个生命周期中。

程序在任何时候都可通过它们来输入/输出数据,所有输入都可来自标准输入流,所有输出都可发送标准输出流,而所有的错误信息则发送到标准错误输出流。

重新包装标准I/O

因为System.out已事先被包装成PrintStream对象,所有我们常常直接使用System.out将数据写到标准输出,同样的,System.err是PrintStream对象,但System.in是一个未被包装的InputStream对象,为了读取到格式化的数据,以及提高读数据的效率,需要对其进行包装。

要把System.in重新包装,先使用InputStreamReader把System.in转换成Reader类,再用BufferedReader来装饰它。

例如:

import java.io.*;
public class first {
	public static void main(String[] args)throws IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));	  //包装标准输入
		PrintWriter out=new PrintWriter(System.out,true);					    //包装标准输出
		String s;															//创建一个字符变量
		while((s=br.readLine())!=null&&s.length()!=0)						    //读取字符信息
			out.println(s.toUpperCase());									   //把字符串转换为大写
	}
}

运行后,在控制台输入:asdfg

运行结果为:

121312

标准I/O流重定向

在默认情况下,标准输入流是从键盘读取数据,标准输出流和标准错误输出流是向控制台输出数据,Java的System类提供了一些简单的静态方法调用,允许对标准输入/输出流和错误I/O流进行重定向。

  • static void setIn(PrintStream in):对标准输入流重定向;

  • static void setOut(PrintStream out):对标准输出流重定向;

  • static void setErr(PrintStream err):对标准错误输出流重定向。

程序向控制台输出大量数据,由于输出数据滚动太快,刷新比较慢,会影响阅读,此时可以把标准输出流定向到一个文件中。

PrintStream中的println方法具有原样输出和自动刷新的功能,这样就可以解决输出数据块,刷新比较慢的问题。

例如:测试标准I/O流的重定向,将标准输入附接到文件上,而将标准输出和标准错误输出定向到另一个文件。

import java.io.*;
public class first {
	public static void main(String[] args)throws IOException {
		PrintStream console=System.out;			//PrintStream,标准输出流
		BufferedInputStream in=new BufferedInputStream(new FileInputStream("G:/table.txt"));   //创建一个BufreredInputStream类实例对象in
		PrintStream out =new PrintStream(new BufferedOutputStream(new FileOutputStream("G:/a.txt")));	//创建一个PrintStream类实例对象out
		System.setIn(in);					   //对标准输入流重定向
		System.setOut(out);					   //对标准输出流重定向
		System.setErr(out);					   //对标准错误输出流重定向
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));	//创建一个BufferedReader类实例对象br,从在键盘中输入或者用户指定的另一个输入源输入
		String s;
		while((s=br.readLine())!=null)			//从BufferedReader类中读取一行数据
			System.out.println(s);			    
		out.close();						  //关闭文本文件
		System.setOut(console);				   //对标准输出流重定向
	}
}

运行该程序,a.txt文本文件将被复制到table.txt文本文件中。

运行结果为:

231321

对象的序列化和反序列化

学习序列化之前,先简单了解数据的状态。数据的状态分两种:

  • 持久态:硬盘上的数据;

  • 游离态:运行在内存中的数据,程序运行结束后,数据就消失了。

序列化与反序列化:

  • 序列化:把游离态的对象写到文件中保存持久态,把Java对象转换为字节序列的过程称为对象的序列化;

  • 反序列化:把文件中的持久态对象读到程序中游离态,把字节序列恢复为Java对象的过程称为对象的反序列化。

对象的序列化主要有两种用途:

  1. 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;

  2. 在网络上传送对象的字节序列。

3213213

默认的序列化机制只将对象的非静态成员变量进行序列化,而任何成员方法和静态成员变量都不参与序列化。序列化时保存的只是变量的值,而变量的任何修饰符都不能保存。

注意:用transient关键字修饰的成员变量,不参与序列化过程。

JDK类库中的序列化API

java.io.ObjectOutputStream代表对象输出流,它的writeObject(Object obj)方法对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中;

java.io.ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化成一个对象,并将其返回。

基本数据类型的包装类、所有容器类甚至Class对象都可以被序列化,但是用户自定义的对象默认是不能序列化的,若要使用一个用户自定义的对象也具备序列化的能力,则必须明确实现java.io.Serializable接口,该接口的定义为:

public interface Serializable{}

该接口未定义任何方法,只是个标记型接口,但只要一个类声明实现了该接口,Java系统就认为该接口可被序列化,该类的对象就可以存盘或通过网络传输了。

例如:创建10个点对象后将它们写入aa.txt文本文件中,然后从该文本文件中读取这10个对象并在控制台显示出来。

import java.io.*;
import java.util.*;
public class first {
	static class Point implements Serializable{			//创建一个静态的Point类并连接接口Serializable
		private int x,y;							  //创建私有变量x,y
		private transient int z;					   //使用关键字transient创建私有变量z
		public Point(int x,int y,int z) {			    //构造方法,传递值
			this.x=x;
			this.y=y;
			this.z=z;
		}
		public String toString() {					   //返回输出格式
			return "("+x+","+y+","+z+")";
		}
	}
	public static void main(String[] args)throws Exception {
		ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("G:/aa.txt"));   //创建ObjectOutputStream对象,使用FileOutputStream类将输出存放在aa.txt文本文件中
		for(int i=0;i<10;i++) {							//利用for循环写入10个点对象到文本文件中
			oos.writeObject(new Point(i,i*2,i*3));
		}
		oos.flush();								   //强制刷新流
		oos.close();								   //关闭文件
		ObjectInputStream ois=new ObjectInputStream(new FileInputStream("G:/aa.txt"));		//创建ObjectInputStream对象,使用FileInputStream类读取aa.txt文件
		for(int k=0;k<10;k++) {					
			Point pt=(Point)ois.readObject();			//利用for循环读取10个点对象
			System.out.print(pt+"");				   //输出点对象
		}
		ois.close();								  //关闭文件
	}
}

运行结果为:

123213

最后

好了,有关Java I/O流——标准I/O、重新包装标准I/O、标准I/O流重定向、对象序列化的知识学到这里了,谢谢观看!!!

我们下篇文章再见!!!

成功不是将来才有的,而是从决定去做的那一刻起,持续累积而成。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白巧克力LIN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值