对象序列化得到的是这个对象的python 二进制数据流流还是这个对象toString之后的python 二进制数据流流呢?

记录和整理!
Java对象序列化详解
所有分布式应用常常需要跨平台,跨网络,因此要求所有传的参数、返回值都必须实现序列化。
  序列化:把Java对象转换为字节序列的过程。
  反序列化:把字节序列恢复为Java对象的过程。
  对象的序列化主要有两种用途:
  1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;(持久化对象)
  2) 在网络上传送对象的字节序列。(网络传输对象)
  实现了如下两个接口之一的类的对象才能被序列化:
  1) Serializable
  2) Externalizable
  序列化:ObjectOutputStream代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。
  反序化:ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。
  注:使用writeObject() 和readObject()方法的对象必须已经被序列化
四、深入理解
一、为什么要序列化?
  Java平台允许我们在内存中创建可复用的Java对象,但只有当JVM(Java虚拟机)处于运行时,这些对象才可能存在,也就是这些对象的生命周期不会比JVM的生命周期更长。但在现实应用中,就可能要求在JVM停止运行之后能够保存指定的对象(持久化对象),并在将来重新读取被保存的对象。Java对象序列化就实现了该功能。
  网络通信时,无论是何种类型的数据,都会转成字节序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。Java对象序列化也实现了该功能。
  所以序列化机制会把内存中的Java对象转换成与平台无关的二进制流,从而永久地保存在磁盘上或是通过网络传输到另一个网络节点。
二、序列化的意义
客户端访问了某个能开启会话功能的资源, web服务器就会创建一个与该客户端对应的HttpSession对象,每个HttpSession对象都要站用一定的内存空间。如果在某一时间段内访问站点的用户很多,web服务器内存中就会积累大量的HttpSession对象,消耗大量的服务器内存,即使用户已经离开或者关闭了浏览器,web服务器仍要保留与之对应的HttpSession对象,在他们超时之前,一直占用web服务器内存资源。
web服务器通常将那些暂时不活动但未超时的HttpSession对象转移到文件系统或数据库中保存,服务器要使用他们时再将他们从文件系统或数据库中装载入内存,这种技术称为Session的持久化。
将HttpSession对象保存到文件系统或数据库中,需要采用序列化的方式将HttpSession对象中的每个属性对象保存到文件系统或数据库中;将HttpSession对象从文件系统或数据库中装载如内存时,需要采用反序列化的方式,恢复HttpSession对象中的每个属性对象。所以存储在HttpSession对象中的每个属性对象必须实现Serializable接口
三、Session的持久化的作用
1.提高服务器内存的利用率,保证那些暂停活动的客户端在会话超时之前继续原来的会话
2,在多台web服务器协同对外提供服务的集群系统中,使用Session的持久化技术,某台服务器可以将其中发生改变的Session对象复制给其他服务器。保证了在某台服务器停止工作后可以由其他服务器来接替它与客户端的会话
3,在一个web应用程序重启时,服务器也会持久化该应用程序中所有HttpSession对象,保证客户端的会话活动仍可以继续。
Tomcat使用Session Manager 类来管理Session的持久化,他提供了两个SessionManager类
org.apache.catalina.session.StandardManager
org.apache.catalina.session.PersistentManager
StandardManager是tomcat默认使用的,在web应用程序关闭时,对内存中的所有HttpSession对象进行持久化,把他们保存到文件系统中。默认的存储文件为
四、serialVersionUID
如果serialVersionUID没有显式生成,系统就会自动生成一个。此时,如果在序列化后我们将该类作添加或减少一个字段等的操作,系统在反序列化时会重新生成一个serialVersionUID然后去和已经序列化的对象进行比较,就会报序列号版本不一致的错误。为了避免这种问题, 一般系统都会要求实现serialiable接口的类显式的生明一个serialVersionUID。
 显式定义serialVersionUID的两种用途:
   1、 希望类的不同版本对序列化兼容时,需要确保类的不同版本具有相同的serialVersionUID;
   2、 不希望类的不同版本对序列化兼容时,需要确保类的不同版本具有不同的serialVersionUID。
五、序列化机制算法
  1. 所有保存到磁盘中的对象都有一个序列化编号
  2. 当程序试图序列化一个对象时,程序先检查该对象是否已经被序列化过。如果从未被序列化过,系统就会将该对象转换成字节序列并输出;如果已经序列化过,将直接输出一个序列化编号。
  要被序列化的对象对应的类的代码:
public class Person implements Serializable {
private String name = null;
private Integer age = null;
public Person(){
System.out.println("无参构造");
public Person(String name, Integer age) {
this.name =
this.age =
public String toString() {
return "[" + name + ", " + age+"]";
  MySerilizable 是一个简单的序列化程序,它先将一个Person对象保存到文件person.txt中,然后再从该文件中读出被存储的Person对象,并打印该对象。
public class MySerilizable {
public static void main(String[] args) throws Exception {
File file = new File("person.txt");
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));
Person person = new Person("Peter", 27);
out.writeObject(person);
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
Object newPerson = in.readObject();
in.close();
System.out.println(newPerson);
  输出结果:
[Peter, 27]
结果没有打印“无参构造”,说明反序列化机制无需通过构造器来初始Java对象。
  1.) 反序列化读取的仅仅是Java对象的数据,而不是Java类,所以在反序列化时必须提供该Java对象所属类的class文件(这里是Person.class),否则会引发ClassNotFoundException异常。
  2).当重新读取被保存的Person对象时,并没有调用Person的任何构造器,说明反序列化机制无须通过构造器来初始化对象。
七、选择序列化
  当对某个对象进行序列化时,系统会自动将该对象的所有属性依次进行序列化,如果某个属性引用到别一个对象,则被引用的对象也会被序列化。如果被引用的对象的属性也引用了其他对象,则被引用的对象也会被序列化。 这就是递归序列化。
  有时候,我们并不希望出现递归序列化,或是某个存敏感信息(如银行密码)的属性不被序列化,我们就可通过transient关键字修饰该属性来阻止被序列化。
将上面的Person类的age属性用transient修饰:
transient private Integer age = null;
再去执行MySerilizable的结果为:
[Peter, null]
writeObject()方法与readObject()方法
  使用transient关键字阻止序列化虽然简单方便,但被它修饰的属性被完全隔离在序列化机制之外,导致了在反序列化时无法获取该属性的值,而通过在需要序列化的对象的Java类里加入writeObject()方法与readObject()方法可以控制如何序列化各属性,甚至完全不序列化某些属性(此时就transient一样)。
  如果我们想要上面的Person类里的name属性在序列化后存在文件里不让别人知道具体是什么(加密),我们就可在Person类里加如下代码:
private void writeObject(ObjectOutputStream out) throws IOException {
out.writeObject(new StringBuffer(name).reverse());
out.writeInt(age);
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
name = ((StringBuffer)in.readObject()).reverse().toString();
age = in.readInt();
详细的自定义序列化与反序列化可参见ObjectOutputStream 和ObjectInputStream 类的JDK文档。
Externalizable接口
Externalizable接口 与Serializable 接口类似,只是Externalizable接口需要强制自定义序列化。
要序列化对象的代码:
public class Teacher implements Externalizable{
public Teacher(){
System.out.println("无参构造");
public Teacher(String name,Integer age){
System.out.println("有参构造");
this.name =
this.age =
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(new StringBuffer(name).reverse());
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
name = ((StringBuffer) in.readObject()).reverse().toString();
public String toString() {
return "[" + name + ", " + age+ "]";
主函数代码改为:
public class MySerilizable {
public static void main(String[] args) throws Exception {
File file = new File("person.txt");
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));
Teacher person = new Teacher("Peter", 27);
out.writeObject(person);
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
Object newPerson = in.readObject();
in.close();
System.out.println(newPerson);
打印结果:
[Peter, null]
八、单例模式的序列化
当我们使用Singleton模式时,应该是期望某个类的实例应该是唯一的,但如果该类是可序列化的,那么情况可能略有不同。此时对第2节使用的Person类进行修改,使其实现Singleton模式,如下所示:
public class Person implements Serializable {
private static class InstanceHolder {
private static final Person instatnce = new Person("John", 31, "男");
public static Person getInstance() {
return InstanceHolder.
private String name = null;
private Integer age = null;
private Gender gender = null;
private Person() {
System.out.println("无参构造");
private Person(String name, Integer age, String gender) {
System.out.println("有参构造");
this.name =
this.age =
this.gender =
同时要修改MySerilizable 应用,使得能够保存/获取上述单例对象,并进行对象相等性比较,如下代码所示:
public class MySerilizable {
public static void main(String[] args) throws Exception {
File file = new File("person.txt");
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));
out.writeObject(Person.getInstance());
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
Object newPerson = in.readObject();
in.close();
System.out.println(newPerson);
System.out.println(Person.getInstance() == newPerson);
打印结果:
[John, 31, 男]
九、序列化对象注意事项
对象的类名、属性都会被序列化;而方法、static属性(静态属性)、transient属性(即瞬态属性)都不会被序列化(这也就是第4条注意事项的原因)
虽然加static也能让某个属性不被序列化,但static不是这么用的
要序列化的对象的引用属性也必须是可序列化的,否则该对象不可序列化,除非以transient关键字修饰该属性使其不用序列化。
反序列化地象时必须有序列化对象生成的class文件(很多没有被序列化的数据需要从class文件获取)
当通过文件、网络来读取序列化后的对象时,必须按实际的写入顺序读取。
没有更多推荐了,java不用数据库持久化对象及数据(java对象的序列化)
 将对象及数据在网上进行传送(是直接将对象数据弄成序列化传送):当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。
将对象数据持久化到电脑或者其他地方,已被以后读入。java在不用数据库的情况下,需要配置的时候,配置的相关对象及数据就可以序列化到本机中,下次运行的时候直接读出配置即可。此外,java不用数据库的情况,可以持久化到文档中,但是那样很麻烦。
  只能将支持 java.io.Serializable 接口的对象写入流中。每个 serializable
对象的类都被编码,编码内容包括类名和类签名、对象的字段值和数组值,以及从初始对象中引用的其他所有对象的闭包。
  序列化:把Java对象转换为字节序列的过程。
  反序列化:把字节序列恢复为Java对象的过程。
  对象的序列化主要有两种用途:
  1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
  2) 在网络上传送对象的字节序列。
3.对象序列化
3.1序列化API
  java.io.ObjectOutputStream代表对象输出流,它的writeObject(Object
obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。只有实现了Serializable和Externalizable接口的类的对象才能被序列化。
  java.io.ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。
3.2代码示例
package com.denchao.useful.
import java.io.FileOutputS
import java.io.ObjectOutputS
import java.io.S
import java.util.D
public class Testtt {
public static void main(String[] args) throws Exception
&//序列化对象
&ObjectOutputStream out = new
ObjectOutputStream(new
FileOutputStream("D:\\objectFile.obj"));
&Customer customer = new Customer("王麻子", 24);
&out.writeObject("你好!"); &
&//写入字面值常量
&out.writeObject(new Date()); &
&//写入匿名Date对象
&out.writeObject(customer); &
&//写入customer对象
&out.close();
&//反序列化对象
&ObjectInputStream in = new ObjectInputStream(new
FileInputStream("D:\\objectFile.obj"));
&System.out.println("obj1 " + (String)
in.readObject()); &
&//读取字面值常量
&System.out.println("obj2 " + (Date)
in.readObject()); &
&//读取匿名Date对象
&Customer obj3 = (Customer) in.readObject();
& &//读取customer对象
&System.out.println("obj3 " + obj3);
&in.close();
class Customer implements Serializable {
& &private String
& &public Customer(String
name, int age) {
&this.name =
&this.age =
& &public String toString()
&return "name=" + name + ", age=" +
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。C#把对象序列化成二进制文件
static void SaveAsBinaryFormat(object obj,string filename)
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter binFormat =
new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
using(System.IO.Stream fsStream = new System.IO.FileStream(filename,System.IO.FileMode.Create,
System.IO.FileAccess.Write,System.IO.FileShare.None))
binFormat.Serialize(fsStream, obj);
没有更多推荐了,如何:向/自二进制流对对象进行序列化和反序列化(实体框架)
如何:向/自二进制流对对象进行序列化和反序列化
本文档已存档,并且将不进行维护。
如何:向/自二进制流对对象进行序列化和反序列化(实体框架)
Visual Studio 2010
由 实体数据模型
(EDM) 生成器工具 (EdmGen.exe) 和 Entity Data Model 向导生成的实体类型支持二进制序列化。
当将对象序列化为二进制流时,也将对当前加载到对象上下文中的所有相关对象进行序列化。
有关更多信息,请参见。
本主题中的示例基于 。
若要运行本示例中的代码,必须已将 AdventureWorks 销售模型添加到您的项目中,并将项目配置为使用实体框架。
为此,请完成和 中的过程。
必须针对以下命名控件添加 using 语句(在 Visual Basic 中为 Imports):
在本例中,SerializeToBinaryStream 方法查询 Contact 对象以获得指定的姓氏值,并返回二进制 。
MemoryStream 包含 Contact 对象及其相关的 SalesOrderHeader 和 SalesOrderDetail 对象的对象图。
public static void ReadFromBinaryStream()
BinaryFormatter formatter = new BinaryFormatter();
using (AdventureWorksEntities context = new AdventureWorksEntities())
// Get the object graph for the selected customer
// as a binary stream.
MemoryStream stream = SerializeToBinaryStream(@"Adams");
// Read from the begining of the stream.
stream.Seek(0, SeekOrigin.Begin);
// Deserialize the customer graph from the binary stream
// and attach to an ObjectContext.
Contact contact = (Contact)formatter.Deserialize(stream);
context.Attach(contact);
// Display information for each item
// in the orders that belong to the first contact.
foreach (SalesOrderHeader order in contact.SalesOrderHeaders)
Console.WriteLine(String.Format("PO Number: {0}",
order.PurchaseOrderNumber));
Console.WriteLine(String.Format("Order Date: {0}",
order.OrderDate.ToString()));
Console.WriteLine("Order items:");
foreach (SalesOrderDetail item in order.SalesOrderDetails)
Console.WriteLine(String.Format("Product: {0} "
+ "Quantity: {1}", item.ProductID.ToString(),
item.OrderQty.ToString()));
catch (SerializationException ex)
Console.WriteLine("The object graph could not be deserialized from "
+ "the binary stream because of the following error:");
Console.WriteLine(ex.ToString());
private static MemoryStream SerializeToBinaryStream(string lastName)
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream();
using (AdventureWorksEntities context = new AdventureWorksEntities())
// Specify a timeout for queries in this context, in seconds.
context.CommandTimeout = 120;
// Define a customer contact.
// Create a Contact query with a path that returns
// orders and items for a contact.
ObjectQuery&Contact& query =
context.Contacts.Include("SalesOrderHeaders.SalesOrderDetails");
// Return the first contact with the specified last name
// along with its related orders and items.
customer = query.Where("it.LastName = @lastname",
new ObjectParameter("lastname", lastName)).First();
// Serialize the customer object graph.
formatter.Serialize(stream, customer);
catch (EntitySqlException ex)
throw new InvalidOperationException("The object query failed", ex);
catch (EntityCommandExecutionException ex)
throw new InvalidOperationException("The object query failed", ex);
catch (SerializationException ex)
throw new InvalidOperationException("The object graph could not be serialized", ex);
// Return the streamed object graph.#include&&iostream&#include&&sstream&#include&&boost/archive/binary_iarchive.hpp&#include&&boost/archive/binary_oarchive.hpp&#include&&boost/serialization/utility.hpp&using&namespace&class&Data{&&friend&class&boost::serialization::&&_int64&m_&&template&&class&Archive&&&void&serialize(&Archive&&ar,&const&unsigned&int&version&)&&{&&&&ar&&&m_&&};public:&&Data()&:&m_data(&0&)&{};&&const&_int64&&getData()&const&{&return&m_&};&&void&setData(&_int64&val&){&m_data&=&&}};int&_tmain(int&argc,&_TCHAR*&argv[]){&&&&//&序列化对象&&&&ostringstream&&&&&boost::archive::binary_oarchive&oar(&oss&);&&&&Data&&&&&const&Data&&data_freeze&=&const_cast&Data&&(&data&);&&&&data.setData(&0000000&);&&&&oar&&&&data_&&&&data.setData(&0000000&);&&&&oar&&&&data_&&&&cout&&&&"serialize:&len:"&&&&oss.str().size()&&&&"\n&&&data:"&&&&oss.str()&&&&&&&&//&反序列化&&&&istringstream&iss(&oss.str()&);&&&&boost::archive::binary_iarchive&iar(&iss&);&&&&Data&data1;&&&&iar&&&&data1;&&&&cout&&&&"data:&"&&&&data1.getData()&&&&&&&&iar&&&&data1;&&&&cout&&&&"data:&"&&&&data1.getData()&&&&&&&&getchar();&&&&return&0;}
感觉还不错, 如果将其加入网络数据处理部分应该挺好的, 还有待其他方面测试。
阅读(5172)

我要回帖

更多关于 c 二进制数据流 的文章

 

随机推荐