本文收集整理关于对象的序列化和反序列化的相关议题,使用内容导航快速到达。
内容导航:
Q1:Java对象怎么序列化和反序列化
importjava.io.Serializable;
/*
*NotSerializableException:未序列化异常
*
*类通过实现java.io.Serializable接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。
*该接口居然没有任何方法,类似于这种没有方法的接口被称为标记接口。
*
*java.io.InvalidClassException:
*cn.itcast_07.Person;localclassincompatible:
*streamclassdescserialVersionUID=-2071565876962058344,
*localclassserialVersionUID=-8345153069362641443、*
*为什么会有问题呢?
*Person类实现了序列化接口,那么它本身也应该有一个标记值。
*这个标记值假设是100。
*开始的时候:
*Person.class--id=100
*wirte数据:oos.txt--id=100
*read数据:oos.txt--id=100
*
*现在:
*Person.class--id=200
*wirte数据:oos.txt--id=100
*read数据:oos.txt--id=100
*在实际开发中,可能还需要使用以前写过的数据,不能重新写入。怎么办呢?
*回想一下原因是因为它们的id值不匹配。
*每次修改java文件的内容的时候,class文件的id值都会发生改变。
*而读取文件的时候,会和class文件中的id值进行匹配。所以,就会出问题。
*但是呢,如果有办法,让这个id值在java文件中是一个固定的值,这样,你修改文件的时候,这个id值还会发生改变吗?
*不会。现在的关键是我如何能够知道这个id值如何表示的呢?
*不用担心,不用记住,也没关系,点击鼠标即可。
*难道没有看到黄色警告线吗?
*
*要知道的是:
*看到类实现了序列化接口的时候,要想解决黄色警告线问题,就可以自动产生一个序列化id值。
*而且产生这个值以后,我们对类进行任何改动,它读取以前的数据是没有问题的。
*
*注意:
* 一个类中可能有很多的成员变量,有些我不想进行序列化。请问该怎么办呢?
*使用transient关键字声明不需要序列化的成员变量
*/
publicclassPersonimplementsSerializable{
privatestaticfinallongserialVersionUID=-2071565876962058344L;
privateStringname;
//privateintage;
privatetransientintage;
//intage;
publicPerson(){
super();
}
publicPerson(Stringname,intage){
super();
this.name=name;
this.age=age;
}
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
publicintgetAge(){
returnage;
}
publicvoidsetAge(intage){
this.age=age;
}
@Override
publicStringtoString(){
return"Person[name="+name+",age="+age+"]";
}
}
Q2:ios开发如何进行对象序列化和反序列化
Objective-C可以将程序用到的各种对象序列化到文件,在任何需要的情况下,从文件中重新读取数据重新构造对象,下面说一下对象的序列化和反序列化。
使用NSKeyedArchiver把对象序列化到文件中:
// 数组对象NSString *saveStr1 = @NSKeyedArchiver1″;NSString *saveStr2 = @NSKeyedArchiver2″;NSArray *array = [NSArray arrayWithObjects:saveStr1, saveStr2, nil];// 将路径和文件名合成文件完整路径 NSString *Path
Q3:多个对象序列化和反序列化
没什么好说的,写个例子给你看吧,有些代码用了VS2008的特性,如果你用的是VS2008以下的版本,自己改下吧。
using System;
using System.Text;
using System.IO;
using System.Xml.Serialization;
namespace Demo
{
public class Account
{
public int UserID { get; set; }
public string Username { get; set; }
}
class Program
{
static void Main( string[] args )
{
Account[] accounts = {
new Account(){ UserID = 1, Username = "test1" },
new Account(){ UserID = 2, Username = "test2" },
new Account(){ UserID = 3, Username = "test3" }
};
string savePath = @"c:\XmlSerializerTest.txt";
XmlSerializer xs = new XmlSerializer( typeof( Account[] ) );
using ( TextWriter tw = new StreamWriter( savePath ) )
{
xs.Serialize( tw, accounts );
tw.Close();
using ( TextReader tr = new StreamReader( savePath ) )
{
Account[] deSerializedValue = http://127.0.0.1/yijitao/xs.Deserialize( tr ) as Account[];
if ( deSerializedValue != null && deSerializedValue.Length > 0 )
{
for ( int i = 0; i < deSerializedValue.Length; i++ )
{
Console.WriteLine( "{0}\tUserID = {1}, Username = {2}", i, deSerializedValue[ i ].UserID, deSerializedValue[ i ].Username );
}
}
}
}
Console.ReadKey();
}
}
}
//----------二进制方式,可以使用BinaryFormatter 类来以二进制格式将对象或整个连接对象图形序列化和反序列化
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace Demo
{
[Serializable]
public class Account
{
public int UserID { get; set; }
public string Username { get; set; }
}
class Program
{
static void Main( string[] args )
{
Account[] accounts = {
new Account(){ UserID = 1, Username = "test1" },
new Account(){ UserID = 2, Username = "test2" },
new Account(){ UserID = 3, Username = "test3" }
};
string savePath = @"c:\BinarySerializerTest.bin";
BinaryFormatter formatter = new BinaryFormatter();
using ( FileStream writeStream = new FileStream( savePath, FileMode.Create, FileAccess.Write ) )
{
formatter.Serialize( writeStream, accounts );
//xs.Serialize( tw, accounts );
writeStream.Close();
using ( FileStream readStream = new FileStream( savePath, FileMode.Open, FileAccess.Read ) )
{
Account[] deSerializedValue = http://127.0.0.1/yijitao/formatter.Deserialize( readStream ) as Account[];
if ( deSerializedValue != null && deSerializedValue.Length > 0 )
{
for ( int i = 0; i < deSerializedValue.Length; i++ )
{
Console.WriteLine( "{0}\tUserID = {1}, Username = {2}", i, deSerializedValue[ i ].UserID, deSerializedValue[ i ].Username );
}
}
}
}
Console.ReadKey();
}
}
}
Q4:Java中对象序列化与反序列化的几种形式及各自的特点
这项技术主要应用于RMI(对象作为参数远程传递及返回)和JavaBeans中。 Java中还提供了XMLEncoder和XMDecoder类来将JavaBeans对象序列化到XML文件,但是此种方法有诸多不便对Java类有很多限制(要满足get/set方法等等,否则可能丢失该属性值)。一个很强大的开源工具XStream,也能够将对象保存到一个XML文件,并能从中恢复而且没有那么多限制。将XML作为一种进行对象传递的公共数据格式实现跨平台的进程通信。序列化和反序列化机制的强大在于能够自动处理序列化对象之间的复杂关系(对象之间的相互引用,形成了复杂的对象网,因此要保证这种关系准确无误的存储起来。)。通过反序列化获取对象的方式可以达到深度克隆对象一样的效果,当然在性能上肯定有较大损失。
WwW.yIjiTAo..COm
Q5:深入理解:XML与对象的序列化与反序列化
这篇文章主要讲述XML与对象的序列化与反序列化。并且会附上一些简单的序列化与反序列化方法,供大家使用。
假设我们在一个Web项目中有这样两个类
复制代码 代码如下:
public class Member
{
public string Num { get; set; }
public string Name { get; set; }
}
public class Team
{
public string Name;
public List
}
假设我们需要把Team类的一个实例POST到一个URL,
当然,使用Form隐藏域提交就可以完成该功能。
如果该Team包括30条数据呢?
为了区分每个Member,我们得给参数的名字加上后缀。这就要一大串的隐藏域来完成:
复制代码 代码如下:
@model Team
<script type="text/javascript">
document.getElementById("submitForm").submit();
</script>
还敢想象一下如果Team再复杂一些,嵌套再多一些的情况么?
呃,即使你愿意这么传数据,对方看到一坨参数名就够头疼了。
我们都知道对象是不能在网络中直接传输的,不过还有补救的办法。
XML(Extensible Markup Language)可扩展标记语言,本身就被设计用来存储数据,任何一个对象都可以用XML来描述。以Team类为例:
复制代码 代码如下:
<?xml version="1.0" encoding="utf-8"?>
这样一个XML文档就表示了Team一个实例。
聪明的看官应该已经想到,XML是可以作为对象信息的载体在网络中传输,因为它是文本形式的。
怎么进行XML文档与对象的相互转换呢?
XmlSerializer类就是干这个活的。
命名空间:System.Xml.Serialization
程序集:System.Xml(在 system.xml.dll 中)
现在这里展示了一个提供序列化与反序列化方法的EncodeHelper类。
Deserialize方法将XML字符串转换为指定类型的对象;
Serialize方法则将对象转换为XML字符串。
复制代码 代码如下:
///
/// 提供xml文档序列化 反序列化
///
public sealed class EncodeHelper
{
///
/// 反序列化XML字符串为指定类型
///
public static object Deserialize(string Xml, Type ThisType)
{
XmlSerializer xmlSerializer = new XmlSerializer(ThisType);
object result;
try
{
using (StringReader stringReader = new StringReader(Xml))
{
result = xmlSerializer.Deserialize(stringReader);
}
}
catch (Exception innerException)
{
bool flag = false;
if (Xml != null)
{
if (Xml.StartsWith(Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble())))
{
flag = true;
}
}
throw new ApplicationException(string.Format("Couldnt parse XML: {0}; Contains BOM: {1}; Type: {2}.",
Xml, flag, ThisType.FullName), innerException);
}
return result;
}
///
/// 序列化object对象为XML字符串
///
public static string Serialize(object ObjectToSerialize)
{
string result = null ;
try
{
XmlSerializer xmlSerializer = new XmlSerializer(ObjectToSerialize.GetType());
using (MemoryStream memoryStream = new MemoryStream())
{
XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, new UTF8Encoding(false));
xmlTextWriter.Formatting = Formatting.Indented;
xmlSerializer.Serialize(xmlTextWriter, ObjectToSerialize);
xmlTextWriter.Flush();
xmlTextWriter.Close();
UTF8Encoding uTF8Encoding = new UTF8Encoding(false, true);
result= uTF8Encoding.GetString(memoryStream.ToArray());
}
}
catch (Exception innerException)
{
throw new ApplicationException("Couldnt Serialize Object:" + ObjectToSerialize.GetType().Name, innerException);
}
return result;
}
}
要使用这个类需要添加以下引用
using System;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
下面我们用一个控制台程序来演示一下这个类是如何工作的。这里是程序的Main函数。
复制代码 代码如下:
static void Main(string[] args)
{
List
Member member1 = new Member { Name = "Marry", Num = "001" };
Member member2 = new Member { Name = "John", Num = "002" };
Members.Add(member1);
Members.Add(member2);
Team team = new Team { Name = "Development", Members = Members };
var xml =EncodeHelper.Serialize(team);//序列化
Console.Write(xml);//打印序列化后的XML字符串
Console.ReadLine();
Team newTeam = EncodeHelper.Deserialize(xml, typeof(Team)) as Team;//反序列化时需要显式的进行类型转换
Console.WriteLine("Team Name:"+newTeam.Name);//显示反序列化后的newTeam对象
foreach (var member in newTeam.Members)
{
Console.WriteLine("Member Num:" + member.Num);
Console.WriteLine("Member Name:" + member.Name);
}
Console.ReadLine();
}
在执行完Console.Write(xml)这行代码后,就可以看到打印出来的XML文档了。
复制代码 代码如下:
<?xml version="1.0" encoding="utf-8"?>
与我在文章开头给出的例子是一模一样的。
最终反序列化出来的newTeam对象打印出来是这样的结果。
Team Name:Development
Member Num:001、Member Name:Marry
Member Num:002、Member Name:John
回到我们开头的Web通信的例子,
利用XML序列化与反序列化来进行对象传递,我们只需要把需要传递的对象序列化为XML字符串,使用一个隐藏域进行form提交就可以搞定咯!
接收方再将接收到的XML字符串反序列化成预设的对象即可。前提是双方必须约定序列化与反序列化的过程一致,且对象相同。
最后我们来看一下怎么利用一些特性来控制序列化与反序列化操作的过程。我们把开始的类改一下:
复制代码 代码如下:
public class Member
{
[XmlElement("Member_Num")]
public string Num { get; set; }
public string Name { get; set; }
}
[XmlRoot("Our_Team")]
public class Team
{
[XmlIgnore]public string Name;
public List
}
然后我们再次执行刚才的控制台程序,序列化结果变成了这样:
复制代码 代码如下:
<?xml version="1.0" encoding="utf-8"?>
本来的根节点Team变成了Our_Team,Member的子节点Num变成了Member_Num,并且Team的Name子节点被忽略了。
可见特性XmlRoot可以控制根节点的显示和操作过程,XmlElement则针对子节点。如果某些成员被标记XmlIgnore,则在序列化与反序列化过程中会被忽略。
这些特性的具体内容可以在MSDN查看,就不多讲了。
有了这些知识,在网络中传递对象数据应该已经难不倒各位看官了把。^_^