序列化

title: 用途.
content: 为了达成上述功能其一能有效作用,则必须与硬件结构保持独立性。譬如说为了能最大化分布式的使用,在不同硬件运行的计算机,应该能够可靠地重建序列化资料流,而不依赖于字节序。虽然直接复拷内存中的资料结构更简便又快速,可是对于其它不同硬件的机器,却无法可靠地运作。以独立于硬件之外的格式来序列化资料结构,要避开字节序、内存布局、或在不同编程语言中资料结构如何表示等等之类的问题。  对于任何序列化方案的本质来说,因为资料编码是根据定义连续串在一起的,提取序列化资料结构中的某一部分,则需要从头到尾读取整个物件并且重新建构。这样的资料线性在许多应用中是有利的,因为它使输出入接口简单而共同,能被用来保持及传递物件的状态。  要求高效能的应用时,花费精力处理更复杂的非线性储存系统是有其必要意义的。即使在单一机器上,原始的指针物件也非常脆弱无法保存,因为它们指向的标地可能重新加载到内存中的不同位址。为了处理这个问题,序列化过程包括一个步骤:将参照的直接指针转换为以名称或位置的间接参照,称之为不挥发(unswizzling)或者指针不挥发。反序列化过程则包括了称为指针旋转(swizzling)的反向步骤。由于序列化和反序列化可从共通代码(例如,微软MFC中的"Serialize"函数)驱动,所以共通代码可同时进行两次,因此,  这技术应用在内容随时间变化的使用者界面编程中-依照输入事件来处理图形物件的产生、移除、更改或制作,而无需编写另外的代码执行这些操作。
title: 缺点.
content: 序列化可能会破解抽象资料型别的封装实作,而使其详细内容曝光。简单的序列化实作可能违反物件导向中私有资料成员需要封装(encapsulation)的原则。商用软件的出版商通常会将应用软件的序列化格式,当作商业秘密,以阻碍竞争对手生产可相容的产品;有些会蓄意地混淆,或甚至将序列化资料作加密处理。然而,互通可用性的要求应用程序能够理解彼此的序列化格式。因此,像CORBA的远端方法调用架构详细定义了它们的序列化格式。许多机构,例如档案馆和图书馆,尝试将他们的备份档案-特别是数据库抛档(dump),储存成一些相对具可读性的序列化格式中,使备份资料不因资讯技术变迁而过时。
title: 序列化格式.
content: 20世纪80年代初的全录网络系统快递技术影响了第一个广泛采用的标准。Sun Microsystems在1987年发布了外部数据表示法(XDR)。90年代后期开始推动标准序列化的协议:XML(可延伸标记式语言)应用于产生人类可读的文字编码。资料以这样的编码使存续的物件能有效用,无论相对于人是否可阅读与理解,或与编程语言无关地传递给其它资讯系统。它缺点是失去了扎实的编码字节流,但截至目前技术上所提供大量的储存和传输容量,使得档案大小的考量,已不同于早期计算机科学的重视程度。  二进制XML被提议作为一种妥协方式,它不能被纯文字编辑器读取,但比一般XML更为扎实。在二十一世纪的Ajax技术网页中,XML经常应用于结构化资料在客端和伺服端之间的异步传输。相较于XML,JSON是一种轻量级的纯文字替代,也常用于网页应用中的客端-伺服端通讯。JSON肇基于JavaScript语法所衍生,但也广为其它编程语言所支援。与JSON类似的另一个替代方案是YAML,它包含加强序列化的功能,更“人性化”而且更扎实。这些功能包括标记资料型别,支援非阶层式资料结构,缩排结构化资料的选项以及多种形式的纯量资料引用的概念。  另一种可读的序列化格式是属性列表(property list)。应用在NeXTSTEP、GNUstep和macOS Cocoa环境中。  针对于科学使用的大量资料集合,例如气候,海洋模型和卫星数据,已经开发了特定的二进制序列化标准,例如HDF,netCDF和较旧的GRIB。
title: 编程语言支援.
content: 一些物件导向的编程语言直接支援物件序列化(或物件归档),可借由语法糖元素或者提供了标准接口。这些编程语言其中有Ruby,Smalltalk,Python,PHP,Objective-C,Delphi,Java 和.NET系列语言。若是缺少原生支援序列化的编程语言,也可使用额外的函式库来添加功能。
title: C/C++.
content: C 和 C++ 没有提供任何类型的高阶序列化构造,但是两种语言都支援将内建资料型别以及一般的资料结构codice_1输出为二进制资料。因此,开发人员自己定义序列化函数是显而易举的。此外,基于编译器的解决方案,如用于 C++ 的ODB ORM系统,能够自动产生类别宣告的序列化源码,不必修改或仅少量的修改。其它普及的序列化框架是有来自Boost框架的Boost.Serialization,S11n和Cereal等框架。微软的MFC框架也提供序列化方法,作为其文件视图(Document-View)架构的部件。
title: Java.
content: Java 提供自动序列化,需要以codice_2接口的实例来标明对象。实作接口将类别标明为“可序列化”,然后Java在内部处理序列化。在codice_3接口上并没有预先定义序列化的方法,但可序列化类别可任意定义某些特定名称和签署的方法,如果这些方法有定义了,可被调用执行序列化/反序列化部分过程。该语言允许开发人员以另一个codice_4接口,更彻底地实作并覆盖序列化过程,这个接口包括了保存和恢复物件状态的两种特殊方法。  在默认情况下有三个主要原因使物件无法被序列化。其一,在序列化状态下并不是所有的物件都能获取到有用的语义。例如,codice_5物件绑定到当前Java虚拟机的状态,对codice_5物件状态的反序列化环境来说,没有意义。其二,物件的序列化状态构成其类别相容性缔结(compatibility contract)的某一部分。在维护可序列化类别之间的相容性时,需要额外的精力和考量。所以,使类别可序列化需要慎重的设计决策而非默认情况。其三,序列化允许存取类别的永久私有成员,包含敏感资讯(例如,密码)的类别不应该是可序列化的,也不能外部化。上述三种情形,必须实作codice_3接口来存取Java内部的序列化机制。标准的编码方法将字段简单转换为字节流。  原生型别以及永久和非静态的物件参照,会被编码到字节流之中。序列化物件参照的每个物件,若其中未标明为codice_8的字段,也必须被序列化;如果整个过程中,参照到的任何永久物件不能序列化,则这个过程会失败。开发人员可将物件标记为暂时的,或针对物件重新定义的序列化,来影响序列化的处理过程,以截断参照图的某些部分而不序列化。Java并不使用构造函数来序列化对象。  由JDBC也可对Java物件进行序列化,并将其储存到数据库中。虽然Swing元件的确实例化了Serializable接口,但它们不能移植到有版本差异的Java虚拟机之间。因此,Swing元件或任何继承它的元件可以序列化为字节阵列,但不能保证这个仓存在另一台机器上可读取。
title: Perl.
content: 由CPAN所提供的几个Perl模组提供序列化机制,包括了codice_9,codice_10和codice_11。 codice_9包括将档案或Perl纯量的资料结构,将其序列化和反序列化的功能。除了直接序列化到档案之外,codice_9 还包含了冻结功能,将包装为纯量的资料,返回其序列化的副本;并可用codice_14(解冻)这个纯量来反序列化。这对于以网络插座(socket)发送复杂的资料结构,或将其储存于数据库中非常有用。  当利用Storable对结构进行序列化时,具备了网络安全性的功能,它们以降低一点效能的成本,将资料储存为任何计算机可读取的格式。这些功能的名称有codice_15,codice_16等。依硬件特定的,带字母“n”函数所序列化的这些结构,则以没有字母“n”的函数将之反序列化-常态地解冻并撷取反序列化结构。
title: PHP.
content: PHP最初通过内建的codice_17和codice_18函数来实作序列化。PHP可以序列化任何其它资料类型,除了资源(档案指针,socket等)以外。对不受信任的资料上使用内建的codice_18函数时,通常是有风险的。对于物件有两种“魔术方法”,codice_20和codice_21,可以在类别中实作。而会分别从codice_17和codice_18中呼叫,对应于清理和恢复物件的功能。例如,在序列化时可能需要关闭数据库连线,并在反序列化时恢复连线;这个功能可在这两种魔术方法中处理。它们也允许物件选择哪些属性可被序列化。从PHP 5.1开始有物件导向的序列化机制,即为codice_3接口。
title: Python.
content: Python编程核心的序列化机制是codice_25标准函式库,这名称暗示数据库相关的特别术语“浸渍”,来描述资料反序列化(unpickling for deserializing)。Pickle 使用一个简单的基于堆叠的虚拟机来记录用于重建物件的指令。这是个跨版本并可自订定义的序列化格式,但并不安全(不能防止错误或恶意资料)。错误格式或蓄意构建的资料,可能导致序列反解器汇入任意模组,而且实例化任何物件。  这个函式库有另外包括序列化为标准资料格式的模组:json(内置的基本纯量与集合型别支援,且能够通过编解码支援任何型别)和XML编码的属性列表(codice_26),限于plist支援的类型(数字,字串,布林,元组,串行,字典,日期时间和二进制blob)。最后,建议在正确的环境中评估物件的codice_27,使其和Common Lisp的打印物件大略地相符合。并非所有物件类型可以自动浸渍,特别是那些拥有操作系统资源(如档案把柄)的,但开发人员能注册自订定义的“缩减”和构造功能,来支援任何型别的浸渍和序列化。  Pickle最初是纯粹以Python编程语言来实作的模组,但在Python 3之前的版本中,cPickle模组(也是内建的)提供了更快速的性能。cPickle从Unladen Swallow专案改造而成。在Python 3中,开发人员应该导入标准版本,该版本会尝试导入加速版本并返回纯Python版本。
title: .NET Framework.
content: .NET框架有几个由微软设计的序列化器。第三方协力厂商也有许多序列化器。
title: Delphi.
content: Delphi提供将元件(也称为持续物件)序列化的内建机制,完全与开发环境整合。元件的内容会被保存在DFM档案中,并即时重新加载。
title: OCaml.
content: OCaml的标准函式库提供codice_28模组和codice_29函数,codice_30和codice_31用于编组。虽然OCaml编程是静态类型检查的,但Marshal模组的使用可能会破坏型别保证,因为没有方法能检查反序列的流,是否代表期望型别的物件。OCaml中的函数或含有函数的资料结构(例如带有方法的物件),由于其中的执行码不可以在相异程序之间传输,所以难以将函数编组。(有一个旗标可标示函数代码的位置,但只能在完全相同的程序中解组)。标准编组功能可以配置一个旗标,来共享和循环资料的处理。
title: Smalltalk.
content: 通常,非递回和非共享的物件能利用codice_32协议,以人类可读的形式来储存和撷取。codice_33方法产生一个Smalltalk表达式原文,而以<code>readFrom:<code>评估时:重新建立原始物件。这方案特殊之处在于它利用物件的程序描述,而不是资料本身。因此它非常有弹性,允许更紧密的表示类别定义。不过在其原始形式中,它不处理循环的资料结构,也不保留共享参照的识别(即两个参照对应到单一物件,将被恢复为两个相等的参照,但这两份是不同的副本)。  为此,存在各种可携和非便携式的代替方案。其中一些属于特定的Smalltalk实作或是类别馆。在Squeak Smalltalk中有几种方法可以序列化和储存物件。最简单和最常用的是codice_32,和根基于codice_35二进制储存格式的序列化程序。此外对于包裹物件,可以用</code>ImageSegments</code>来储存和撷取。两者都提供了所谓的“二进制物件仓存框架”,可对紧密二的进制形式执行序列化和撷取。两者都处理循环的、递回的和共享的结构,储存/撷取类别和父类别资讯,并且包括用于“即时”迁移物件的机制(将旧版编写的实例,依照不同物件布局转换成类别)。  这些API(storeBinary/readBinary)虽然彼此相似,但编码细节是不同的,使得这两种格式并不相容。而Smalltalk/X是自由开放源码的,能被加载到其它Smalltalks方言中,允许它们之间能互相交换。物件序列化并非ANSI Smalltalk规范的一部分。因此,序列化物件的代码因Smalltalk实作而异,所得到的二进制资料也不同。例如在Ambrai中就无法恢复在Squeak中所建立的序列化物件。所以,不同Smalltalk实作的各种应用程序,无法在不同实作之间共享资料。这些应用程序包括MinneStore物件数据库和一些RPC包。这个问题的解决方案是SIXX,它是一个使用XML格式进行序列化的Smalltalks的软件包。

Summary: 序列化(serialization)在计算机科学的资料处理中,是指将资料结构或物件状态转换成可取用格式(例如存成档案,存于缓冲,或经由网络中传送),以留待后续在相同或另一台计算机环境中,能恢复原先状态的过程。依照序列化格式重新获取字节的结果时,可以利用它来产生与原始物件相同语义的副本。对于许多物件,像是使用大量参照的复杂物件,这种序列化重建的过程并不容易。物件导向中的物件序列化,并不概括之前原始物件所关联的函式。这种过程也称为物件编组(marshalling)。从一系列字节提取资料结构的反向操作,是反序列化(也称为解编组、deserialization、unmarshalling)。

Serialisierung: Die Serialisierung ist in der Informatik eine Abbildung von strukturierten Daten auf eine sequenzielle Darstellungsform. Serialisierung wird hauptsächlich für die Speicherung von Objekten in Dateien und für die Übertragung von Objekten über das Netzwerk bei verteilten Softwaresystemen verwendet.