- 浏览: 455814 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
飞天奔月:
我来个简单点的代码 使用 LinkedHashSetpubli ...
ArrayList去重 -
飞天奔月:
public static <T> List< ...
ArrayList去重 -
aaron7524:
事务隔离级别 -
月陨殇:
wlh269 写道rswh110 写道lz内容写的不错,就是略 ...
事务隔离级别 -
lnx1824:
我的更奇怪,在本地静态的可以,放jetty里的页面后就不然,都 ...
JS得到上传图片尺寸
简单来说序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化,流的概念这里不用多说(就是I/O),我们可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间(注:要想将对象传输于网络必须进行流化)!在对对象流进行读写操作时会引发一些问题,而序列化机制正是用来解决这些问题的!
问题的引出:
如上所述,读写对象会有什么问题呢?比如:我要将对象写入一个磁盘文件而后再将其读出来会有什么问题吗?别急,其中一个最大的问题就是对象引用!举个例子来说:假如我有两个类,分别是A和B,B类中含有一个指向A类对象的引用,现在我们对两个类进行实例化{ A a = new A(); B b = new B(); },这时在内存中实际上分配了两个空间,一个存储对象a,一个存储对象b,接下来我们想将它们写入到磁盘的一个文件中去,就在写入文件时出现了问题!因为对象b包含对对象a的引用,所以系统会自动的将a的数据复制一份到b中,这样的话当我们从文件中恢复对象时(也就是重新加载到内存中)时,内存分配了三个空间,而对象a同时在内存中存在两份,想一想后果吧,如果我想修改对象a的数据的话,那不是还要搜索它的每一份拷贝来达到对象数据的一致性,这不是我们所希望的!
以下序列化机制的解决方案:
1.保存到磁盘的所有对象都获得一个序列号(1, 2, 3等等)
2.当要保存一个对象时,先检查该对象是否被保存了。
3.如果以前保存过,只需写入"与已经保存的具有序列号x的对象相同"的标记,否则,保存该对象
通过以上的步骤序列化机制解决了对象引用的问题!
序列化的实现
将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。
例子:
修改默认的序列化机制
在序列化的过程中,有些数据字段我们不想将其序列化,对于此类字段我们只需要在定义时给它加上transient关键字即可,对于transient字段序列化机制会跳过不会将其写入文件,当然也不可被恢复。但有时我们想将某一字段序列化,但它在SDK中的定义却是不可序列化的类型,这样的话我们也必须把他标注为transient,可是不能写入又怎么恢复呢?好在序列化机制为包含这种特殊问题的类提供了如下的方法定义:
private void readObject(ObjectInputStream in) throws
IOException, ClassNotFoundException;
private void writeObject(ObjectOutputStream out) throws
IOException;
(注:这些方法定义时必须是私有的,因为不需要你显示调用,序列化机制会自动调用的)
使用以上方法我们可以手动对那些你又想序列化又不可以被序列化的数据字段进行写出和读入操作。
下面是一个典型的例子,java.awt.geom包中的Point2D.Double类就是不可序列化的,因为该类没有实现Serializable接口,在我的例子中将把它当作LabeledPoint类中的一个数据字段,并演示如何将其序列化!
问题的引出:
如上所述,读写对象会有什么问题呢?比如:我要将对象写入一个磁盘文件而后再将其读出来会有什么问题吗?别急,其中一个最大的问题就是对象引用!举个例子来说:假如我有两个类,分别是A和B,B类中含有一个指向A类对象的引用,现在我们对两个类进行实例化{ A a = new A(); B b = new B(); },这时在内存中实际上分配了两个空间,一个存储对象a,一个存储对象b,接下来我们想将它们写入到磁盘的一个文件中去,就在写入文件时出现了问题!因为对象b包含对对象a的引用,所以系统会自动的将a的数据复制一份到b中,这样的话当我们从文件中恢复对象时(也就是重新加载到内存中)时,内存分配了三个空间,而对象a同时在内存中存在两份,想一想后果吧,如果我想修改对象a的数据的话,那不是还要搜索它的每一份拷贝来达到对象数据的一致性,这不是我们所希望的!
以下序列化机制的解决方案:
1.保存到磁盘的所有对象都获得一个序列号(1, 2, 3等等)
2.当要保存一个对象时,先检查该对象是否被保存了。
3.如果以前保存过,只需写入"与已经保存的具有序列号x的对象相同"的标记,否则,保存该对象
通过以上的步骤序列化机制解决了对象引用的问题!
序列化的实现
将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。
例子:
import java.io.*; public class Test { public static void main(String[] args) { Employee harry = new Employee("Harry Hacker", 50000); Manager manager1 = new Manager("Tony Tester", 80000); manager1.setSecretary(harry); Employee[] staff = new Employee[2]; staff[0] = harry; staff[1] = manager1; try { ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream("employee.dat")); out.writeObject(staff); out.close(); ObjectInputStream in = new ObjectInputStream(new FileInputStream( "employee.dat")); Employee[] newStaff = (Employee[]) in.readObject(); in.close(); /** * 通过harry对象来加薪 将在secretary上反映出来 */ newStaff[0].raiseSalary(10); for (int i = 0; i < newStaff.length; i++) System.out.println(newStaff[i]); } catch (Exception e) { e.printStackTrace(); } } } class Employee implements Serializable { public Employee(String n, double s) { name = n; salary = s; } /** * * 加薪水 * */ public void raiseSalary(double byPercent) { double raise = salary * byPercent / 100; salary += raise; } public String toString() { return getClass().getName() + "[name = " + name+ ",salary = " + salary+ "]"; } private String name; private double salary; } class Manager extends Employee { public Manager(String n, double s) { super(n, s); secretary = null; } /** * * 设置秘书 * */ public void setSecretary(Employee s) { secretary = s; } public String toString() { return super.toString()+ "[secretary = " + secretary+ "]"; } // secretary代表秘书 private Employee secretary; }
修改默认的序列化机制
在序列化的过程中,有些数据字段我们不想将其序列化,对于此类字段我们只需要在定义时给它加上transient关键字即可,对于transient字段序列化机制会跳过不会将其写入文件,当然也不可被恢复。但有时我们想将某一字段序列化,但它在SDK中的定义却是不可序列化的类型,这样的话我们也必须把他标注为transient,可是不能写入又怎么恢复呢?好在序列化机制为包含这种特殊问题的类提供了如下的方法定义:
private void readObject(ObjectInputStream in) throws
IOException, ClassNotFoundException;
private void writeObject(ObjectOutputStream out) throws
IOException;
(注:这些方法定义时必须是私有的,因为不需要你显示调用,序列化机制会自动调用的)
使用以上方法我们可以手动对那些你又想序列化又不可以被序列化的数据字段进行写出和读入操作。
下面是一个典型的例子,java.awt.geom包中的Point2D.Double类就是不可序列化的,因为该类没有实现Serializable接口,在我的例子中将把它当作LabeledPoint类中的一个数据字段,并演示如何将其序列化!
import java.io.*; import java.awt.geom.*; public class TransientTest { public static void main(String[] args) { LabeledPoint label = new LabeledPoint("Book", 5.00, 5.00); try { System.out.println(label);// 写入前 ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("Label.txt")); out.writeObject(label); out.close(); System.out.println(label);// 写入后 ObjectInputStream in = new ObjectInputStream(new FileInputStream("Label.txt")); LabeledPoint label1 = (LabeledPoint) in.readObject(); in.close(); System.out.println(label1);// 读出并加1.0后 } catch (Exception e) { e.printStackTrace(); } } } class LabeledPoint implements Serializable { public LabeledPoint(String str, double x, double y) { label = str; point = new Point2D.Double(x, y); } private void writeObject(ObjectOutputStream out) throws IOException { /** * * 必须通过调用defaultWriteObject()方法来写入 * * 对象的描述以及那些可以被序列化的字段 * */ out.defaultWriteObject(); out.writeDouble(point.getX()); out.writeDouble(point.getY()); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { /** * * 必须调用defaultReadObject()方法 * */ in.defaultReadObject(); double x = in.readDouble() + 1.0; double y = in.readDouble() + 1.0; point = new Point2D.Double(x, y); } public String toString() { return getClass().getName()+ "[label = " + label+ ", point.getX() = " + point.getX()+ ", point.getY() = " + point.getY()+ "]"; } private String label; transient private Point2D.Double point; }
发表评论
-
java开发实战视频详解
2017-07-02 08:09 510java开发实战视频详解 链接: http://pan.bai ... -
ArrayList去重
2013-04-25 10:18 3294public static List removeDuplic ... -
java ArrayList 自定义排序
2013-04-22 11:39 2159import java.util.ArrayList; imp ... -
按照指定编码读取配置文件
2012-12-13 10:17 895BufferedReader reader = new Buf ... -
java读取系统编码
2012-12-13 09:45 896public static void main(String[ ... -
Axis2和现有项目的集成
2011-08-11 10:08 1398axis2和现有项目集成 1.下载axis2-1.5-war. ... -
阻塞队列
2010-09-03 08:54 1226ArrayBlockingQueue为阻塞队列,加入和取出元素 ... -
axis2和JDK1.5开发(文件传输服务)详解二(图解)
2010-06-28 16:36 22925.生成webservice服务端代 ... -
产生随机字符串
2010-05-05 17:13 1061import java.util.Random; p ... -
常用IO操作
2009-09-22 13:22 1306例子:写文件,在文件末尾追加文字并且指定输出文件内容字符编码为 ... -
FileChannel锁定文件
2009-09-22 10:52 2415当FileLock fl = fc.tryLock();执行成 ... -
SOCKET 文件传输
2009-09-21 15:47 4250要求将服务端文件夹A下的文件拷贝到客户端文件A下 删除服务端文 ... -
ZIP 压缩 和解压缩
2009-09-21 15:40 1125package com.socket.zip.util; ... -
Oracle number类型查询精度丢失问题
2009-08-21 16:00 6792一、需求中要求查到一个字段的值然后保持小数点后2位 ... -
Oracle number类型数据取出来后四舍五入到小数点后2位
2009-08-19 10:46 8128package com.wlh.test; impo ... -
将汉字编码为unicode
2009-07-28 10:26 888package test; import java. ... -
验证码
2009-07-05 17:29 1283验证servlet: package edu.yale. ... -
java.util.Date对象和String对象转换 SimpleDateFormat
2009-06-30 15:35 3068import java.text.ParseExcept ... -
Socket高级编程 多客户端
2009-06-26 14:03 2566客户端: package com.wlh.test; ... -
进制转换
2009-06-18 12:48 115716进制和字符串之间转换--- import java ...
相关推荐
在.NET框架中,有两种常见的序列化方式:二进制序列化和XML序列化。这两种方法各有优缺点,适用于不同的场景。 一、二进制序列化 二进制序列化是.NET框架提供的一种高效的数据序列化方式,它将对象转换为字节流,以...
### 二进制序列化与反序列化 #### 一、概述 在.NET框架中,序列化是一项重要的功能,它允许开发人员将对象的状态转换成一种可以存储或传输的形式。通常,序列化有两种主要实现方式:**二进制序列化**(通过`...
序列化 (serialization):将对象的状态信息转换为可以存储或传输的形式的过程。 与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。 序列化的目的 1、以某种存储形式使...
C#提供了多种序列化机制,如XML序列化、二进制序列化、JSON序列化等,每种都有其特定的应用场景。 二、XML序列化 XML序列化将对象转换为XML格式的字符串,易于阅读和交换。在C#中,可以使用`XmlSerializer`类实现...
- **JSON数据**:序列化二进制数据,使其能在JSON格式中传输。 - **文件存储**:将文件内容编码为Base64字符串,存储在数据库或其他文本文件中。 ### 7. 文件名列表中的"DeserializeStr" 在给定的压缩包文件中,...
C#自定义可序列化的Dictionary类型 在C#中,Dictionary类型是非常常用的数据结构,但是.NET 2.0中的泛型Dictionary却不支持XML序列化。这是一种非常不便的限制,因为在实际应用中,我们经常需要将数据序列化到XML...
这是一个用C#写的Socket服务器和客户端,当然Socket服务器和客户端不是主要的(有兴趣的朋友可以参考下),主要的内容是介绍如何通过这种Socket方式发送Object对象。 作者博客 http://luyugao.com
在C#中,我们可以使用.NET框架提供的`System.Runtime.Serialization.Formatters.Binary.BinaryFormatter`类来进行二进制序列化,或者使用`System.Xml.Serialization.XmlSerializer`来进行XML序列化。而在Java中,...
**二、JSON反序列化** 反序列化是将JSON字符串恢复为C++对象的过程。继续以nlohmann/json为例: 1. 从JSON字符串创建json对象: ```cpp std::string jsonString = R"({"name":"John","age":30})"; json j = json::...
本文将深入探讨Hessian框架的基础知识,它是一个高效的二进制序列化协议,广泛应用于Java和.NET之间跨语言通信。通过学习Hessian,我们可以更有效地处理数据传输,提高应用性能。 首先,让我们理解什么是序列化。...
本篇将深入探讨如何在C#中进行二进制数组与常规数组之间的转换,以及二进制序列化和JSON序列化的应用及其反序列化过程。 首先,让我们来看看二进制数组与常规数组之间的转换。在C#中,二进制数组通常用byte[]表示,...
在C#编程中,二进制序列化是一个重要的概念,它允许我们将对象的状态转换为字节流,以便存储或在网络上传输。这个过程是通过.NET框架提供的System.Runtime.Serialization命名空间中的类来实现的。本实例将深入探讨...
序列化是将一个对象的状态转换为可以存储或传输的形式,通常是XML、JSON或二进制格式。这样做的好处在于,我们可以保存对象的状态并在稍后恢复,或者将对象发送到远程服务器。在C#中,我们可以使用ISerializable接口...
本资源聚焦于C#中的二进制序列化,这是一种效率高、数据紧凑的序列化方式。下面将详细阐述二进制序列化的概念、使用方法以及它在实际开发中的应用。 二进制序列化是.NET框架提供的一种机制,它可以将对象转换为原始...
序列化DLL文件通常涉及将内存中的函数、变量和类结构转换为二进制流或XML等文本格式,以便在磁盘上保存或通过网络发送。反序列化则是将这个流恢复为原来的函数和数据结构,使其能够在应用程序中正常工作。 接下来,...
#### 二、序列化的应用场景 序列化在多种场景下都非常有用: 1. **对象持久化**:当你希望将内存中的对象状态保存到文件或数据库中时,序列化是一种非常有效的方式。例如,在游戏开发中,可以通过序列化保存玩家的...
相比于XML或JSON等文本格式,protobuf的序列化结果更小,解析速度更快,因为它是二进制编码。此外,protobuf提供了强大的类型定义,支持复杂的数据结构,包括消息嵌套、数组和枚举类型,使得数据结构更加清晰和易于...
序列化是指将一个对象的状态转换为可存储或传输的形式,通常是二进制流;反序列化则相反,是将这个二进制流恢复为原来的对象。在本案例中,我们将关注如何将文本信息加密成二进制文件,以确保数据的安全性和不可读性...
在IT行业中,序列化和反序列化是两个关键的概念,特别是在对象持久化、数据传输以及存储方面。在Delphi编程环境中,这两个概念同样至关重要。本文将深入探讨Delphi中的序列化与反序列化,以及如何处理组件和结构体的...
在Java开发中,msgpack工具库提供了对这种二进制序列化和反序列化的支持,尤其适用于大数据处理、网络通信以及分布式系统中的数据交换。 **序列化与反序列化** 序列化是将对象转换为可存储或可传输的形式的过程,...