JavaIO——System对IO的支持、序列化
1、系统类对IO的支持
在我们学习PriteWriter、PrintStream里面的方法print、println的时候是否观察到其与我们之前一直使用的系统输出很相似呢?其实我们使用的系统输出就是采用IO模式完成的。
在System中定义了三个操作的常量:
a、标准输出:(System.out) public final static PrintStream out
b、错误输出:(System.err) public final static PrintStream err
c、标准输入:(System.in) public final static InputStream in
(1)系统输出
out和err常量都为系统输出,都是PrintStream类对象。
两者之间的区别在于:out输出的内容是希望用户看到的内容而err输出的是不希望用户看到的。其中err只是一个保留的属性,现在几乎用不到。
由其结构可以看出System.out是PrintStream的实例化对象,而由类图可得PrintStream是OutputStream的子类,所以可以直接使用System.out直接为OutputStream实例化,这个时候的OutputStream输出的位置将变为屏幕。
-
/*
-
* 系统输出
-
* */
-
public class Test3{
-
public static void main(String[] args) throws IOException {
-
OutputStream outputStream = System.out;
-
outputStream.write("你好!".getBytes());
-
}
-
}
(2)系统输入
与前面两者不同的是System.in是InputStream的对象。而这种输入操作是指用户通过键盘输入(用户输入)。Java本身并没有直接的用户输入,所以要想实现这样的操作,还得借助java.io模式来完成。
-
/*
-
* 系统输入
-
* */
-
public class Test3{
-
public static void main(String[] args) throws IOException {
-
InputStream inputStream = System.in;
-
byte[] data = new byte[1024];
-
System.out.println("请输入:");
-
//将数据读取到字节数组中
-
int temp = inputStream.read(data);
-
System.out.println("输出为:"+new String(data,0,temp));
-
inputStream.close();
-
}
-
}
通过程序我们可以发现:当用户输入信息时程序需要暂停执行,这是因为程序进入了阻塞状态,直至我们输入操作完成后按回车,程序才可以继续向下进行。且以上程序中我们是采用开辟固定长度的字节数组,当我们输入的字节大于该固定长度时就会出现读取部分数据的结果。这是因为一次读取不完造成的结果。所以我们将引入内存流对其进行改进,先将这些数据保存在内存流中然后一次性进行取出。
-
/*
-
* 输入字节数大于开辟数组的大小
-
* */
-
public class Test3{
-
public static void main(String[] args) throws IOException {
-
InputStream inputStream = System.in;
-
byte[] data = new byte[16];
-
System.out.println("请输入:");
-
//将数据读取到字节数组中
-
int temp = inputStream.read(data);
-
System.out.println("输出为:"+new String(data,0,temp));
-
inputStream.close();
-
}
-
}
-
/*
-
* 内存流进行改进操作
-
* */
-
public class Test3{
-
public static void main(String[] args) throws IOException {
-
InputStream inputStream = System.in;
-
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
-
byte[] data = new byte[16];
-
System.out.println("请输入:");
-
int temp = 0;
-
while((inputStream.read(data)) != -1) {
-
//保存数据到内存输出流中
-
byteArrayOutputStream.write(data,0,temp);
-
//用户判断输入结束
-
if(temp < data.length) {
-
break;
-
}
-
break;
-
}
-
inputStream.close();
-
byteArrayOutputStream.close();
-
System.out.println("输出为:"+new String(byteArrayOutputStream.toByteArray()));
-
}
-
}
由此我们可以发现虽然实现了用键盘输入数据的功能,但是使得整体的实现逻辑过于混乱,所以说java提供的System.in并不好用,还要结合内存流来完成,复杂度很高。
如果要想在IO中进行中文的处理,最好的做法是将所有输入的数据保存在一起再处理,这样才可以保证不出现乱码。
由此我们可以引入java提供的两种输入流:
(3)输入流(BufferedReader和Scanner)
A、BufferedReader类
BufferReader类是一个缓冲输入流,且是字符流的操作对象。
缓冲流也可分为两类:字节缓冲流((BufferedInputStream)和字符缓冲流(BufferedReader)。
我们之所以选择BufferReader类操作,是因为在该类中提供有如下方法(读取一行数据)
public String readLine() throws IOException这个方法可以直接读取一行数据,以回车为换行符。
但是当我们观察BufferReader类及其构造函数:
public class BufferedReader extends Reader
public BufferedReader(Reader in)而我们使用的System.in是InputStream的子类和Reader并没有直接的关系,所以我们需要建立他们之间的联系:利用InputStreamReader类。
-
/*
-
* 利用BufferedReader类实现键盘输入
-
* */
-
public class Test3{
-
public static void main(String[] args) throws IOException {
-
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
-
System.out.println("请输入:");
-
//默认使用回车换行,默认的换行模式也是BufferReader的缺点
-
String string = bufferedReader.readLine();
-
System.out.println("输出为:"+string);
-
}
-
}
使用以上形式实现的键盘输入还有一个大特点,由于接收的数据类型为String,可以使用String类的各种操作进行数据处理并且可以变为各种常见数据类型。且该类在jdk1.5后被java.util.Scanner所替代。
B、Scanner类
Scanner类在java.util包下;
打印流解决的是OutputStream类的缺陷,BefferedReader解决的是InputStream类的缺陷。而Scanner解决的是 BefferedReader类的缺陷(替换了BefferedReader类)
Scanner是一个专门进行输入流处理的程序类,利用这个类可以方便处理各种数据类型,同时也可以直接结合正则表达式进行各项处理,在这个类中主要关注以下方法:
1. 判断是否有指定类型数据: public boolean hasNextXxx()
2. 取得指定类型的数据: public 数据类型 nextXxx() 只要有数据输入,遇到第一个空格、回车、制表符都会终止读取数据。
public 数据类型 nextLine()只以回车符终止(遇到空格、制表符仍然继续进行读取)
3. 定义分隔符:public Scanner useDelimiter(Pattern pattern)
4. 构造方法:public Scanner(InputStream source)
-
/*
-
* 使用Scanner类实现数据输入
-
* */
-
public class Test3{
-
public static void main(String[] args) {
-
Scanner scanner = new Scanner(System.in);
-
System.out.println("请输入:");
-
//有输入内容不判断空字符串
-
if(scanner.hasNext()) {
-
//遇到空格、制表符、回车均停止数据的读取
-
// System.out.println("输入内容为:"+scanner.next());
-
//只有遇到回车才停止数据的读取
-
System.out.println("输入内容为:"+scanner.nextLine());
-
}
-
scanner.close();
-
}
-
}
通过上述运行结果我们可以验证nextXXX()方法进行相应数据类型数据的读取时,只要遇到空格就停止读取数据。
最为重要的是,Scanner可以对接收的数据类型使用正则表达式判断。
-
/*
-
* 自定义格式输出
-
* */
-
public class Test3{
-
public static void main(String[] args) {
-
Scanner scanner = new Scanner(System.in);
-
System.out.println("请输入出生日期:");
-
if(scanner.hasNext("\\d{4}-\\d{2}-\\d{2}")) {
-
String string = scanner.nextLine();
-
System.out.println("出生日期为:"+string);
-
}else {
-
System.out.println("输入格式错误");
-
}
-
}
-
}
使用Scanner本身能够接收的是一个InputStream对象,那么也就意味着可以接收任意输入流,例如:文件输入流;Scanner完美的替代了BufferedReader,而且更好的实现了InputStream的操作。
-
/*
-
* 使用Scanner操作文件
-
* */
-
public class Test3{
-
public static void main(String[] args) throws FileNotFoundException {
-
String singal = File.separator;
-
Scanner scanner = new Scanner(new FileInputStream(
-
new File("C:"+singal+"Users"+singal+"lenovo"+singal+"Desktop"+singal+"Test2.txt")));
-
//自定义分隔符
-
scanner.useDelimiter("\n");
-
while(scanner.hasNext()) {
-
System.out.println(scanner.next());
-
}
-
scanner.close();
-
}
-
}
所以以后除了二进制文件拷贝的处理之外,只要是针对程序的信息输出都是用打印流(PrintStream、 PrintWriter),信息输出使用Scanner。
2、序列化
(1)概念
所谓的序列化指的是将程序中的属性以二进制流的形式在网络上传输或者保存在文件中。
可进行序列化的要求:并不意味着所有类的对象都可以被序列化,需要被序列化的类对象往往需要传输使用,同时这个类必须实现 java.io.Serializable接口。这个接口并没有任何的方法定义,只是一个标识而已。
(2)序列化与反序列化的实现
如果要想实现序列化与反序列化的对象操作,在java.io包中提供有两个处理类:ObjectOutputStream、ObjectInputStream
-
/*
-
* 实现序列化与反序列化
-
* */
-
//定义要被序列化的类
-
class Student implements Serializable{
-
private String name = "lemon";
-
//要使用包装类
-
private Integer age = 20;
-
Student(String name, Integer age) {
-
super();
-
this.name = name;
-
this.age = age;
-
}
-
//覆写toString方法
-
public String toString() {
-
return "Student [name=" + name + ", age=" + age + "]";
-
}
-
-
}
-
public class Test3{
-
static String singal = File.separator;
-
public static final File FILE = new File(
-
"C:"+singal+"Users"+singal+"lenovo"+singal+"Desktop"+singal+"Test2.txt");
-
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
-
achieveSer(new Student("lemon",10));
-
opsiteSer();
-
}
-
//实现序列化操作
-
public static void achieveSer(Object object) throws FileNotFoundException, IOException {
-
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(FILE));
-
objectOutputStream.writeObject(object);
-
objectOutputStream.close();
-
}
-
//反序列化操作
-
public static void opsiteSer() throws FileNotFoundException, IOException, ClassNotFoundException {
-
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(FILE));
-
System.out.println(objectInputStream.readObject());
-
objectInputStream.close();
-
}
-
}
实现序列化:
实现反序列化:
(3)transient关键字
由于Serializable默认会将对象中所有属性进行序列化保存,如果现在某些属性不希望被保存了,那么就可以 使用transient关键字。
修改上述代码(在age属性上加transient关键字)
-
//定义要被序列化的类
-
class Student implements Serializable{
-
private String name = "lemon";
-
//要使用包装类
-
private transient Integer age = 20;
-
Student(String name, Integer age) {
-
super();
-
this.name = name;
-
this.age = age;
-
}
-
//覆写toString方法
-
public String toString() {
-
return "Student [name=" + name + ", age=" + age + "]";
-
}
-
-
}
-
public class Test3{
-
static String singal = File.separator;
-
public static final File FILE = new File(
-
"C:"+singal+"Users"+singal+"lenovo"+singal+"Desktop"+singal+"Test2.txt");
-
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
-
achieveSer(new Student("lemon",10));
-
opsiteSer();
-
}
-
//实现序列化操作
-
public static void achieveSer(Object object) throws FileNotFoundException, IOException {
-
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(FILE));
-
objectOutputStream.writeObject(object);
-
objectOutputStream.close();
-
}
-
//反序列化操作
-
public static void opsiteSer() throws FileNotFoundException, IOException, ClassNotFoundException {
-
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(FILE));
-
System.out.println(objectInputStream.readObject());
-
objectInputStream.close();
-
}
-
}
对age属性使用transient关键字后的序列化结果:
对age属性使用transient关键字后的序列化结果:
JavaIO——System对IO的支持、序列化的更多相关文章
- java的IO操作:System类对IO的支持。
目标: 1,掌握SYStem对IO的三种支持: system.out system.in system.err 2,掌握system.out及system.err的区别. 3,掌握输入,输出重定向. ...
- java ->IO流_序列化流与反序列化流
序列化流与反序列化流 用于从流中读取对象的操作流 ObjectInputStream 称为 反序列化流 用于向流中写入对象的操作流 ObjectOutputStream 称为 序列化流(对象 ...
- Azure Messaging-ServiceBus Messaging消息队列技术系列4-复杂对象消息是否需要支持序列化和消息持久化
在上一篇中,我们介绍了消息的顺序收发保证: Azure Messaging-ServiceBus Messaging消息队列技术系列3-消息顺序保证 在本文中我们主要介绍下复杂对象消息是否需要支持序列 ...
- Java IO(Properties/对象序列化/打印流/commons-io)
Java IO(Properties/对象序列化/打印流/commons-io) Properties Properties 类表示了一个持久的属性集.Properties 可保存在流中或从流中加载. ...
- IO流的序列化和反序列化
序列化和反序列化的概念: 序列化:把对象转换为字节序列的过程称为对象的序列化.(常见的就是存文件) 反序列化:把字节序列恢复为对象的过程称为对象阿德反序列化. 序列化和反序列化的使用: java.io ...
- Newtonsoft.Json高级用法,json序列号,model反序列化,支持序列化和反序列化DataTable,DataSet,Entity Framework和Entity,字符串
原文地址:https://www.cnblogs.com/yanweidie/p/4605212.html 手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口 ...
- 一:Newtonsoft.Json 支持序列化与反序列化的.net 对象类型;
导航目录: Newtonsoft.Json 概述 一:Newtonsoft.Json 支持序列化与反序列化的.net 对象类型: 二:C#对象.集合.DataTable与Json内容互转示例: ...
- 通过System.CommandLine快速生成支持命令行的应用
一直以来,当我们想让我们的控制台程序支持命令行启动时,往往需要编写大量代码来实现这一看起来很简单的功能.虽然有一些库可以简化一些操作,但整个过程仍然是一个相当枯燥而乏味的过程.我之前也写过一些文章简单 ...
- hive-相关报错处理${system:java.io.tmpdir}
在使用hive的时候启动成功 [root@localhost bin]# ./hive which: no hbase in (/usr/local/hive/apache-hive-2.1.1-bi ...
随机推荐
- 二,zabbix与php的一些问题
zabbix 检查先决条件 一.php-bcmath 不支持 php 安装 bcmath 扩展(编译安装) PHP的linux版本需要手动安装BCMath扩展,在PHP的源码包中默认包含BCMath的 ...
- shell脚本 PHP+swoole的安装
#!bin/bash set -e # Check if user is root if [ $(id -u) != "0" ]; then echo "Error: p ...
- prometheus(2)之对kubernetes的监控
prometheus服务发现 1.基于endpoints的service注释服务自动发现. 2.基于pod注释的服务自动发现 3.基于consul注册的服务自动发现 4.手动配置服务发现 5.push ...
- win10各版本激活码
win + x进入Power shell(管理员),依次输入 Win10专业版 slmgr.vbs /upk slmgr /ipk W269N-WFGWX-YVC9B-4J6C9-T83GX slmg ...
- LeetCode-40. 组合总和 II C++(回溯法)
回溯法本身是种暴力解法,虽然效率之类的比较低,但是写起来比较易懂和快.在提交之后的排名也挺低的,大概就超过8%左右.以后复习的时候再去看看题解,看看更高性能的算法.这里先暂时贴上回溯法的代码. 最后说 ...
- Part 18 $http service in AngularJS
In Angular there are several built in services. $http service is one of them. In this video, we will ...
- 设计模式学习-使用go实现外观模式
外观模式 定义 适用范围 代码实现 优点 缺点 关于接口粒度的思考 参考 外观模式 定义 外观模式也叫门面模式 外观模式(Facade),为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接 ...
- 测试开发【提测平台】分享14-Vue图标Icon几种用法并利用其一优化菜单
微信搜索[大奇测试开],关注这个坚持分享测试开发干货的家伙. 回归主线更新,由于本次知识点只有一个,就不给思维导图了,在上系列测试平台开发实践中主要学习了页面直接的转跳方法和远程搜索的如何做,最终实现 ...
- 18.jvm调优工具及案例分析
目标: Jmap.Jstack.Jinfo详解 JvisualVm调优工具实战 JVM内存或CPU飙高如何定位 JState命令预估JVM运行情况 系统频繁Full GC导致系统卡顿实战调优 内存泄漏 ...
- cesium开发(1)搭建 vue + cesium开发环境
进入新公司一段时间了,新公司业务主要从事卫星方面等webgl的开发,主要使用了leafletjs和cesium,其中cesium难度较大,需求较多,再进行了一段时间的使用开发后依旧感到有些力不从心, ...