系统学习 Java IO (十二)----数据流和对象流
DataInputStream/DataOutputStream
允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。
要想使用数据输出流和输入流,必须按指定的格式保存数据,才可以将数据输入流将数据读取进来,所以通常使用 DataInputStream 来读取 DataOutputStream 写入的数据。
DataInputStream 类能够从 InputStream 中读取 Java 基本类型(int,float,long等),而不仅仅是原始字节。 将InputStream包装在 DataInputStream 中,就可以从 DataInputStream 中读取 Java 基本类型。 这就是为什么它被称为 DataInputStream - 因为它读取数据(数字)而不仅仅是字节。
如果需要读取的数据包含大于一个字节的Java 基本类型,则 DataInputStream 非常方便。DataInputStream 希望接受有序多字节类型数据。
同时使用 DataInputStream 和 DataOutputStream
如前所述,DataInputStream 类通常与 DataOutputStream 一起使用,首先使用 DataOutputStream 写入数据,然后使用 DataInputStream 再次读取数据。 以下是示例Java代码:
public class DataStream {
public static void main(String[] args) throws IOException {
String file = "D:\\test\\output.txt";
DataOutputStream output = new DataOutputStream(new FileOutputStream(file));
output.write(1); // 默认是 byte
output.writeInt(123); // 指定写入 int
output.writeInt(321);
output.writeLong(789);
output.writeFloat(123.45f);
output.close();
// 一定要按照写入的顺序和类型读取,否则会出错;
DataInputStream input = new DataInputStream(new FileInputStream(file));
byte b = (byte) input.read();
int i1 = input.readInt();
int i2 = input.readInt();
Long l = input.readLong();
Float f = input.readFloat();
input.close();
System.out.println("i1 = " + i1);
System.out.println("i2 = " + i2);
System.out.println("b = " + b);
System.out.println("l = " + l);
System.out.println("f = " + f);
}
}
注意:一定要按照写入的顺序和类型读取,否则会出错;
其实 DataInputStream 类的实现中,读取方法中只有一个 read() 方法是真正干活,其他的 readXXX() 都是调用 read() 完成任务。看如下代码:
public final byte readByte() throws IOException {
int ch = in.read();
if (ch < 0)
throw new EOFException();
return (byte)(ch);
}
public final char readChar() throws IOException {
int ch1 = in.read();
int ch2 = in.read();
if ((ch1 | ch2) < 0)
throw new EOFException();
return (char)((ch1 << 8) + (ch2 << 0));
}
public final int readInt() throws IOException {
int ch1 = in.read();
int ch2 = in.read();
int ch3 = in.read();
int ch4 = in.read();
if ((ch1 | ch2 | ch3 | ch4) < 0)
throw new EOFException();
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}
可以看到,XXX 占 多少个字节,就会在其内部调用多少次 read() 方法。
ObjectInputStream/ObjectOutputStream
和 DataInputStream 包装成 Java 基本类型类似,ObjectInputStream 类能够从 InputStream 中读取Java对象,而不仅仅是原始字节。 当然,读取的字节必须表示有效的序列化 Java 对象。 通常,使用 ObjectInputStream 来读取 ObjectOutputStream 编写(序列化)的对象。
下面是一个例子:
public class ObjectStream {
public static void main(String[] args) throws Exception {
// Serializable 是一个标识接口,实现类只要承诺能被序列化就行了
class People implements Serializable {
String name;
int age;
}
File file = new File("D:\\test\\object.data");
ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream(file));
People someOne = new People();
someOne.name = "Json";
someOne.age = 18;
output.writeObject(someOne);
output.close();
ObjectInputStream input = new ObjectInputStream(new FileInputStream(file));
People people = (People) input.readObject();
System.out.println("name = " + people.name + ", age = " + people.age);
input.close();
}
}
Close()
使用完数据流后记得关闭它。 关闭 DataInputStream 还将关闭 DataInputStream 正在读取的 InputStream 实例。可以使用 try-with-resources 方式自动关闭。ObjectInputStream 同理。
Serializable
如果一个类要进行序列化和反序列化,就必须实现 Serializable 标记接口,这样就可以使用 ObjectOutputStream 完成 Java 对象序列化(写入),使用 ObjectInputStream 完成反序列化(读取)。
Serializable 是一个标记接口意味着它不包含任何方法。 因此,实现 Serializable 的类不必实现任何特定方法,只是告诉 Java 该类对象支持序列化。
serialVersionUID
除了实现 Serializable 接口之外,用于序列化的类还应包含名为 serialVersionUID 的 private static final long 变量。
Java 的对象序列化 API 使用 serialVersionUID 变量来确定反序列化对象是否是使用相同版本的类进行序列化的,因为它现在正尝试将其反序列化。
想象一下,Person 对象被序列化为磁盘。 然后对 Person 类进行更改。 然后反序列化存储的 Person 对象。 这样,序列化的 Person 对象可能与 Person 类的新版本不对应。
要检测此类问题,实现 Serializable 的类应包含 serialVersionUID 字段。 如果对类进行了重大更改,则还应更改其 serialVersionUID 值。
许多 Java IDE 包含生成 serialVersionUID 的工具,可以使用工具生成的 UID 。
在今天的世界(2015年之后)中,许多 Java 项目使用与 Java 序列化机制不同的机制来序列化 Java 对象。 例如,Java 对象被序列化为 JSON,BSON 或其他更优化的二进制格式。 这具有以下优点:对象也可由非 Java 应用程序读取。 例如,在 Web 浏览器中运行的 JavaScript 可以本地序列化和反序列化 JSON 中的对象。
顺便说一下,这些其他对象序列化机制通常不需要 Java 类实现 Serializabl e。 他们通常使用 Java 反射来检查类,这里是 Java IO 教程,具体要看看 Java Json 的教程了。
系统学习 Java IO (十二)----数据流和对象流的更多相关文章
- 系统学习 Java IO (十六)----这么多类,应该用哪个?
目录:系统学习 Java IO---- 目录,概览 Java IO目的和功能 Java IO 包含 InputStream,OutputStream,Reader 和 Writer 类的许多子类. 原 ...
- 系统学习 Java IO (十四)----字符读写缓存和回退 BufferedReader/BufferedWriter & PushbackReader
目录:系统学习 Java IO---- 目录,概览 BufferedReader BufferedReader 类构造器接收一个 Reader 对象,为 Reader 实例提供缓冲. 缓冲可以加快 I ...
- 系统学习 Java IO (十五)----字符读写 Reader/Writer 其他子类
目录:系统学习 Java IO---- 目录,概览 跟踪行号的缓冲字符输入流 LineNumberReader LineNumberReader 类是一个 BufferedReader ,用于跟踪读取 ...
- 系统学习 Java IO (十)----回退流 PushbackInputStream
目录:系统学习 Java IO---- 目录,概览 PushbackInputStream 旨在从 InputStream 解析数据时使用. 有时您需要先读取几个字节以查看将要发生的事情,然后才能确定 ...
- 系统学习 Java IO ---- 目录,概览
Java IO 类的系统教程,原创.主要参考自英文教程 Java IO Tutorial 和 Java Doc. http://tutorials.jenkov.com/java-io/index.h ...
- 系统学习 Java IO (一)----输入流和输出流 InputStream/OutputStream
目录:系统学习 Java IO ---- 目录,概览 InputStream 是Java IO API中所有输入流的父类. 表示有序的字节流,换句话说,可以将 InputStream 中的数据作为有序 ...
- 系统学习 Java IO (八)----装饰流 FilterInputStream/FilterOutputStream
目录:系统学习 Java IO---- 目录,概览 这两个流的作用是:"封装其它的输入流,并为它们提供额外的功能" 他们的直接子类有: BufferedInputStream 的作 ...
- 系统学习 Java IO (二)----IO 异常处理
目录:系统学习 Java IO---- 目录,概览 我们使用流后,需要正确关闭 Streams 和 Readers / Writers . 这是通过调用 close() 方法完成的,看看下面这段代码: ...
- JAVA IO分析二:字节数组流、基本数据&对象类型的数据流、打印流
上一节,我们分析了常见的节点流(FileInputStream/FileOutputStream FileReader/FileWrite)和常见的处理流(BufferedInputStream/B ...
随机推荐
- 简明Python3教程 11.数据结构
简介 数据结构基本上就是 – 可以将一些数据结合到一起的结构,换言之用于存储一组相关的数据. python拥有4种内建数据结构 – 列表,元组(tuple),字典和集合. 我们将看到如何它们,它们又是 ...
- ASP.NET Core macOS 环境配置 - ASP.NET Core 基础教程 - 简单教程,简单编程
原文:ASP.NET Core macOS 环境配置 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 是对 ASP.NET 有重大意义的一次重新设计.本章节我 ...
- 生意经:凡是现今比较会赚钱或是规模比较大的软件公司大都属于开发"消费型软件"的公司(而且登广告,应该定低价进行销售)
c#之父是Anders Hejlsberg, 一个丹麦天才.他和idsoft的John Carmack都是自学成才的典范. 他对语言和汇编的理解全世界没几个人能超越. (今天偶然从网上了解到这个大牛, ...
- NS2网络模拟(6)-homework02.tcl
1: #NS2_有线部分\homework02.tcl 2: 3: #Create a simulator object 4: set ns [new Simulator] 5: 6: #Define ...
- HDU5187 zhx's contest(计数问题)
主题链接: http://acm.hdu.edu.cn/showproblem.php?pid=5187 题意: 从1~n,有多少种排列 使得 a1~ai 满足单调递增或者单调递减. ai~an 满足 ...
- Windows系统时间(FILETIME和SYSTEMTIME)
转载请标明出处,原文地址:http://blog.csdn.net/morewindows/article/details/8654298 欢迎关注微博:http://weibo.com/MoreWi ...
- WPF使用矢量字体图标(阿里巴巴iconfont)
原文:WPF使用矢量字体图标(阿里巴巴iconfont) 版权声明:本文为博主原创文章,转载请注明出处. https://blog.csdn.net/lwwl12/article/details/78 ...
- PD生成兼容Oracle、Mysql脚本
mysql date 改为 datetime ->运行sql脚本 Oracle " clustered " 替换为空,即key(XX) ->运行sql脚本
- 在WPF里面实现以鼠标位置为中心缩放移动图片
原文:在WPF里面实现以鼠标位置为中心缩放移动图片 在以前的文章使用WPF Resource以及Transform等技术实现鼠标控制图片缩放和移动的效果里面,介绍了如何在WPF里面移动和放大缩小图片, ...
- 通过.NET客户端调用Web API(C#)
3.2 Calling a Web API From a .NET Client (C#) 3.2 通过.NET客户端调用Web API(C#) 本文引自:http://www.asp.net/web ...