当前位置:文档之家› 序列化储存

序列化储存

序列化储存
序列化储存

文档与序列化

一、文档的基本特征

文档类文件是从CDocument继承而来的。

The CDocument class provides the basic functionality for user-defined document classes. A document represents the unit of data that the user typically opens with the File Open command and saves with the File Save command.

翻译:文档类提供用户自定义文档类的基本功能。一个文档的打开命令和保存命令是数据单元特征。

CDocument supports standard operations such as creating a document, loading it, and saving it. The framework manipulates documents using the interface defined by CDocument.

翻译:文档类支持标准操作有:创建文档,载入文档,和保存。框架界面使用由文档类定义的界面。

An application can support more than one type of document; for example, an application might support both spreadsheets and text documents. Each type of document has an associated document template; the document template specifies what resources (for example, menu, icon, or accelerator table) are used for that type of document. Each document contains a pointer to its associated CDocTemplate object.

翻译:一个应用程序可以支持多于一种类型的文档;例如,一个应用程序可能同时支持电子表格和普通文本文档。每一种类型的文档有一种关联文档模板;文档模板指定了(例如,菜单,图标,或者加速表格)使用这些类型的文档。每个文档包含一个指针指向关联的模板对象。

Users interact with a document through the CView object(s) associated with it. A view renders an image of the document in a frame window and interprets user input as operations on the document. A document can have multiple views associated with it. When the user opens a window on a document, the framework creates a view and attaches it to the document. The document template specifies what type of view and frame window are used to display each type of document.

翻译:用户将一个文档和一个视类对象想关联起来。一个视类扮演一个嵌入在文档框架内的图像,在文档内解释用户的输入操作。一个文档可以有多个视类与其关联。当用户在一个文档上打开一个窗体,框架创造一个视图,把它放在文档上。文档模板指定适合于用户文档类型的相同类的视图和框架窗口用来显示用户打开的文件。

Documents are part of the framework's standard command routing and consequently receive commands from standard user-interface components (such as the File Save menu item). A document receives commands forwarded by the active view. If the document doesn't handle a given command, it forwards the command to the document template that manages it.

翻译:文档是一个框架标准命令路由,因此从标准用户界面组件(如文件保存菜单项)接受命令。一个文档由其活动视图迅速接受命令。如果该文档没有没有响应给出的命令,那么该命令将交由文档模板来管理。

When a document's data is modified, each of its views must reflect those modifications. CDocument provides the UpdateAllViews member function for you to notify the views of such changes, so the views can repaint themselves as necessary. The framework also prompts the user to save a modified file before closing it.

翻译:当一个文档数据发生改变,每一个它的视图将随即发生改变。文档类提供更新所有视图成员函数来通报每一个视图的改变,因此视图可以在必要的时候被重绘。框架也在关闭前迅速保存改动文件。

To implement documents in a typical application, you must do the following:

●Derive a class from CDocument for each type of document.

●Add member variables to store each document's data.

●Implement member functions for reading and modifying the

document's data. The document's views are the most important users

of these member functions.

●Override the CObject::Serialize member function in your document

class to write and read the document's data to and from disk. 翻译:在一个典型类型的应用程序中实现一个文档,你必须按以下步骤:

●为每一种类型的文档从CDocument派生一个类

●增加成员函数来存储每一个文档的数据

●为读写文档数据实现成员函数。文档视图类是这个成员函数最重要的使

用者。

●在你的文档类重载CObject::Serialize成员函数,来将文档数据从磁

盘读写。

序列化:

本文解释 Microsoft 基础类库 (MFC) 中提供的序列化机制,该机制使对象可以在程序运行之间保持。

序列化是指将对象写入永久性存储媒体(如磁盘文件)或从其中读取对象的进程。MFC 对 CObject 类中的序列化提供内置支持。因此,所有从 CObject 派生的类都可利用 CObject 的序列化协议。

序列化的基本思想是对象应能将其当前状态(通常由该对象的成员变量指示)写入永久性存储中。以后,通过从存储中读取对象状态或反序列化对象状态,可以重新创建该对象。序列化处理序列化对象时使用的对象指针和对象循环引用的所有详细资料。关键之处在于对象本身负责读写其自身状态。因此,对于可序列化的类,必须实现基本的序列化操作。正如“ 序列化” 文章组中所显示的那样,很容易将该功能添加到类中。

MFC 将 CArchive 类的对象用作将被序列化的对象和存储媒体之间的中介物。该对象始终与 CFile 对象相关联,它从 CFile 对象获得序列化所需的信息,包括文件名和请求的操作是读取还是写入。执行序列化操作的对象可在不考虑存储媒体本质的情况下使用 CArchive 对象。

CArchive 对象使用重载输出运算符 (<<) 和输入运算符 (>>) 来执行读写操作。有关更多信息,请参见“ 序列化:序列化对象” 文章中的通过存档存储和加载CObjects。

注意请不要将 CArchive 类与通用 iostream 类混淆, iostream 类只用于格式化的文本。而 CArchive 类则用于二进制格式的序列化对象。

如果愿意,可以不使用 MFC 序列化而为永久性数据存储创建自己的机制。您将需要在用户的命令处重写启动序列化的类成员函数。请参见 ID_FILE_OPEN 、ID_FILE_SAVE 及 ID_FILE_SAVE_AS 标准命令的技术说明22 中的讨论。

下列文章介绍了序列化所需的两个主要任务:

●序列化:创建可序列化的类

●序列化:序列化对象

序列化:序列化与数据库输入/输出的对比一文描述了序列化在数据库应用程序中何时是适当的输入 / 输出技术。

通过存档存储和加载 CObjects

通过存档存储及加载 CObject 需要额外注意。在某些情况下,应调用对象的Serialize 函数,其中, CArchive 对象是 Serialize 调用的参数,与使用CArchive 的“<<”或“>>”运算符不同。要牢记的重要事实是: CArchive 的“>>”运算符基于由存档先前写到文件的 CRuntimeClass 信息构造内存中的 CObject 。

因此,是使用 CArchive 的“<<”和“>>”运算符还是调用 Serialize ,取决于是否需要加载存档基于先前存储的 CRuntimeClass 信息动态地重新构造对象。在下列情况下使用 Serialize 函数:

●反序列化对象时,预先知道对象的确切的类。

●反序列化对象时,已为其分配了内存。

警告如果使用 Serialize 函数加载对象,也必须使用 Serialize 函数存储对象。不要使用 CArchive 的“<<”运算符先存储,然后使用

Serialize 函数进行加载;或使用 Serialize 函数存储,然后使用

CArchive 的“>>”运算符进行加载。

以下示例阐释了这些情况:

class CMyObject : public CObject

{

// ...Member functions

public:

CMyObject() { }

virtual void Serialize( CArchive& ar ) { }

// Implementation

protected:

DECLARE_SERIAL( CMyObject )

};

class COtherObject : public CObject

{

// ...Member functions

public:

COtherObject() { }

virtual void Serialize( CArchive& ar ) { }

// Implementation

protected:

DECLARE_SERIAL( COtherObject )

};

class CCompoundObject : public CObject

{

// ...Member functions

public:

CCompoundObject();

virtual void Serialize( CArchive& ar );

// Implementation

protected:

CMyObject m_myob; // Embedded object

COtherObject* m_pOther; // Object allocated in constructor

CObject* m_pObDyn; // Dynamically allocated object

//..Other member data and implementation

DECLARE_SERIAL( CCompoundObject )

};

IMPLEMENT_SERIAL(CMyObject,CObject,1)

IMPLEMENT_SERIAL(COtherObject,CObject,1)

IMPLEMENT_SERIAL(CCompoundObject,CObject,1)

CCompoundObject::CCompoundObject()

{

m_pOther = new COtherObject; // Exact type known and object already //allocated.

m_pObDyn = NULL; // Will be allocated in another member function // if needed, could be a derived class object.

}

void CCompoundObject::Serialize( CArchive& ar )

{

CObject::Serialize( ar ); // Always call base class Serialize.

m_myob.Serialize( ar ); // Call Serialize on embedded member.

m_pOther->Serialize( ar ); // Call Serialize on objects of known exact type.

// Serialize dynamic members and other raw data

if ( ar.IsStoring() )

{

ar << m_pObDyn;

// Store other members

}

else

{

ar >> m_pObDyn; // Polymorphic reconstruction of persistent

// object

//load other members

}

}

总之,如果可序列化的类将嵌入的 CObject 定义为成员,则不应使用该对象的CArchive 的“<<” 和“>>” 运算符,而应调用 Serialize 函数。同时,如果可序列化的类将指向 CObject (或从 CObject 派生的对象)的指针定义为成员,但在自己的构造函数中将其构造为其他对象,则也应调用 Serialize 。

序列化:创建可序列化的类

ms-help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.2052/vccore/html/_core_seri alization.3a_.making_a_serializable_class.htm

使类可序列化需要五个主要步骤。下面列出了这些步骤并在以后章节内进行了解释:

1.从CObject 派生类(或从CObject 派生的某个类中派生)。

2.重写Serialize 成员函数。

3.使用DECLARE_SERIAL 宏(在类声明中)。

4.定义不带参数的构造函数。

5.为类在实现文件中使用IMPLEMENT_SERIAL 宏。

如果直接调用Serialize而不是通过 CArchive的“>>”和“<<”运算符调用,则序列化不需要最后三个步骤。

从CObject 派生类

在 CObject 类中定义了基本的序列化协议和功能。正如在 CPerson 类的下列声明中所示,通过从 CObject 中(或从 CObject 的派生类中)派生类,可获得对CObject 的序列化协议及功能的访问权限。

重写 Serialize 成员函数

在 CObject 类中定义的 Serialize 成员函数实际上负责对捕获对象的当前状态所必需的数据进行序列化。 Serialize 函数具有 CArchive 参数,该函数使用其来读写对象数据。 CArchive 对象具有成员函数 IsStoring ,该成员函数指示 Serialize 正在存储(即正在写入数据)还是正在加载(即正在读取数据)。用 IsStoring 的结果作为参考,使用输出运算符 (<<) 将对象数据插入到CArchive 对象中或使用输入运算符 (>>) 提取数据。

假定一个类是从 CObject 派生的并具有两个新成员变量,分别为 CString 和WORD 类型。下列类声明段显示了新成员变量和重写的 Serialize 成员函数的声明:

class CPerson : public CObject

{

public:

DECLARE_SERIAL( CPerson )

// empty constructor is necessary

CPerson(){};

CString m_name;

WORD m_number;

void Serialize( CArchive& archive );

// rest of class declaration

};

重写 Serialize 成员函数

1.调用Serialize 的基类版本以确保序列化对象的继承部分。

2.插入或提取您的类所特定的成员变量。

输出运算符及输入运算符与存档类交互作用以读写数据。下面的示例显示了如何实

现以上声明的 CPerson类的Serialize:

void

CPerson:: Serialize( CArchive

&

archive )

{

//

call base

//

base clas

CObjec

//

now do th

if

( archive.

archive

<<

m_name

<<

m_number;

else

>>

m_name

>>

m_number;

}

也可使用 CArchive::Read及 CArchive::Write成员函数来读写大量未键入的数据。

使用DECLARE_SERIAL 宏

在支持序列化的类的声明中需要DECLARE_SERIAL宏,如下所示:

class

CPerson :

public

CObject

{

DECLARE_SERIAL( CPerson )

//

rest o

f declaration follows

}

;

定义不带参数的构造函数

反序列化对象(从磁盘上加载)后,MFC 重新创建这些对象时,需要一个默认的构造函数。反序列化进程将用重新创建对象所需的值填充所有成员变量。

可将该构造函数声明为公共的、受保护的或私有的。如果使该构造函数成为受保护的或私有的,请确保它将仅由序列化函数使用。该构造函数必须使对象处于这样一种状态:必要时,可允许将其安全删除。

注意如果忘记在使用DECLARE_SERIAL 及IMPLEMENT_SERIAL 宏的类中

定义不带参数的构造函数,将在使用IMPLEMENT_SERIAL 宏的行上得到“没有可用的默认构造函数”编译器警告。

在实现文件中使用IMPLEMENT_SERIAL 宏

IMPLEMENT_SERIAL宏用于定义从CObject中派生可序列化类时所需的各种函数。在类的实现文件 (.CPP) 中使用这个宏。该宏的前两个参数是类名和直接基类的名称。

该宏的第三个参数是架构编号。架构编号实质上是类对象的版本号。架构编号使用大于或等于零的整数。(请不要将该架构编号与数据库术语混淆。)

MFC 序列化代码在将对象读取到内存时检查该架构编号。如果磁盘上对象的架构编号与内存中类的架构编号不匹配,库将引发CArchiveException,防止程序读取对象的不正确版本。

如果要使 Serialize成员函数能够读取多个版本(即,读取用应用程序的不同版本写入的文件),可将VERSIONABLE_SCHEMA值作为IMPLEMENT_SERIAL宏的参数。有关用法信息和示例,请参见CArchive类的GetObjectSchema成员函数。

以下示例显示了如何将IMPLEMENT_SERIAL用于从CObject派生的 CPerson类。

IMPLEMENT_SERIAL( CPerson, CObject, 1 )

正如序列化:序列化对象文章中所讨论的,一旦具有可序列化的类,就可以序列化类的对象。序列化:序列化对象

序列化:创建可序列化的类一文说明如何使类可序列化。一旦具有可序列化的类,就可以通过 CArchive对象将该类的对象序列化到文件和从文件序列化该类的对象。本文将解释:

?CArchive 对象的定义。

?两种方法创建 CArchive 。

?使用 CArchive << 和 >> 运算符的方法。

?通过存档存储和加载 CObjects 。

可使框架创建可序列化文档的存档或自己显式创建CArchive对象。通过使用CArchive的“<<”和“>>”运算符或在某些情况下通过调用CObject派生类的Serialize 函数,可在文件和可序列化对象间传输数据。

什么是Archive对象?

CArchive对象提供了一个类型安全缓冲机制,用于将可序列化对象写入CFile对象或从中读取可序列化对象。通常,CFile对象表示磁盘文件;但是,它也可以是表示“剪贴板”的内存文件(CSharedFile对象)。

给定的CArchive对象要么存储数据(即写入数据或将数据序列化),要么加载数据(即读取数据或将数据反序列化),但决不能同时进行。CArchive对象的寿命只限于将对象写入文件或从文件读取对象的一次传递。因此,需要两个连续创建的CArchive对象将数据序列化到文件,然后从文件反序列化数据。

当存档将对象存储到文件时,存档将CRuntimeClass名称附加到这些对象。然后,当另一个存档将对象从文件加载到内存时,将基于这些对象的CRuntimeClass动态地重新构造CObject派生的对象。通过存储存档将给定对象写入文件时,该对象可能被引用多次。然而,加载存档将仅对该对象重新构造一次。有关存档如何将CRuntimeClass信息附加到对象以及重新构造对象(考虑可能的多次引用)的详细信息,请参见技术说明 2 。

将数据序列化到存档时,存档积累数据,直到其缓冲区被填满为止。然后,存档将其缓冲区写入CArchive对象指向的CFile对象。同样,当您从存档中读取数据时,存档会将数据从文件读取到它的缓冲区,然后从缓冲区读取到反序列化的对象。这种缓冲减少了物理读取硬盘的次数,从而提高了应用程序的性能。

创建 CArchive 对象有两种方法:

●通过框架隐式创建 CArchive 对象

●显式创建 CArchive 对象

通过框架隐式创建 CArchive 对象

最普通且最容易的方法是使框架代表“文件”菜单上的“保存”、“另存为”和“打开”命令为文档创建 CArchive 对象。

以下是应用程序的用户从“文件”菜单上发出“另存为”命令时,框架所执行的操作:

显示“另存为”对话框并从用户获取文件名。

打开用户命名的文件作为 CFile 对象。

创建指向该 CFile 对象的 CArchive 对象。在创建 CArchive 对象时,框架将模式设置为“存储”(即写入或序列化),而不是“加载”(即读取或反序列化)。调用在 CDocument 派生类中定义的 Serialize 函数,将 CArchive 对象的引用传递给该函数。

然后,文档的 Serialize 函数将数据写入 CArchive 对象(刚作了解释)。从Serialize 函数返回时,框架先销毁 CArchive 对象,再销毁 CFile 对象。

因此,如果让框架为文档创建 CArchive 对象,您所要做的一切是实现写入存档和从存档中读取的文档的 Serialize 函数。您还必须为文档的 Serialize 函数直接或间接依次序列化的任何 CObject 派生对象实现 Serialize 。

显式创建 CArchive 对象

除了通过框架将文档序列化之外,在其他场合也可能需要 CArchive 对象。例如,可能要序列化到达或来自剪贴板的数据,由 CSharedFile 对象表示。或者,可能要使用用户界面来保存与框架提供的文件不同的文件。在这种情况下,可以显式创建 CArchive 对象。使用下列过程,用与框架采用的相同方式来执行此操作。显式创建 CArchive 对象

构造 CFile 对象或从 CFile 导出的对象。

按照下面示例所示,将 CFile 对象传递到 CArchive 的构造函数:

CFile theFile;

theFile.Open(..., CFile::modeWrite);

CArchive archive(&theFile, CArchive::store);

CArchive 构造函数的第二个参数是指定存档将用于向文件中存储数据还是用于从文件中加载数据的枚举值。对象的 Serialize 函数通过调用存档对象的IsStoring 函数来检查该状态。

当完成向 CArchive 对象存储数据或从该对象中加载数据时,关闭该对象。虽然CArchive 对象(和 CFile 对象)会自动关闭存档(和文件),好的做法是显式执行,因为这使从错误恢复更为容易。有关错误处理的更多信息,请参见异常:捕捉和删除异常一文。

关闭 CArchive 对象

以下示例阐释了如何关闭 CArchive 对象:

archive.Close();

theFile.Close();

使用 CArchive 对象的“ << ”和“ >> ”操作符

CArchive 提供“ << ”和“ >> ”运算符,用于向文件中写入简单的数据类型和 CObjects 以及从文件中读取它们。

通过存档将对象存储在文件中

以下示例显示了如何通过存档将对象存储在文件中:

CArchive ar(&theFile, CArchive::store);

WORD wEmployeeID;

...

ar << wEmployeeID;

从先前存储在文件中的值加载对象

以下示例显示了如何从先前存储在文件中的值加载对象:

CArchive ar(&theFile, CArchive::load);

WORD wEmployeeID;

...

ar >> wEmployeeID;

通常,通过 CObject 派生类的 Serialize 函数中的存档将数据存储到文件中或从文件中加载数据,必须已用 DECLARE_SERIALIZE 宏来声明这些函数。将CArchive 对象的引用传递到 Serialize 函数。调用 CArchive 对象的IsLoading 函数以确定是否已调用 Serialize 函数来从文件中加载数据或将数据存储到文件中。

可序列化的 CObject 派生类的 Serialize 函数通常具有以下形式:

void CPerson::Serialize(CArchive& ar)

{

CObject::Serialize(ar);

if (ar.IsStoring())

{

// TODO: add storing code here

}

else

{

// TODO: add loading code here

}

}

上面的代码模板与 AppWizard 为该文档(从 CDocument 派生的类)的Serialize 函数所创建的代码模板完全相同。由于存储代码和加载代码总是并行,该代码模板有助于写的代码更容易复查,如下例中所示:

void CPerson:Serialize(CArchive& ar)

{

if (ar.IsStoring())

{

ar << m_strName;

ar << m_wAge;

}

else

{

ar >> m_strName;

ar >> m_wAge;

}

}

库将 CArchive 的“ << ”和“ >> ”运算符定义为第一操作数,将下列数据类

注意通过存档存储及加载 CObjects 需要额外注意。有关更多信息,请参见通过存档存储和加载 CObjects 。

CArchive 的“ << ”和“ >> ”运算符总是返回 CArchive 对象的引用,该引用为第一操作数。这使您可以链接运算符,如下所示:

BYTE bSomeByte;

WORD wSomeWord;

DWORD wSomeDoubleWord;

...

ar << bSomeByte << wSomeWord << wSomeDoubleWord;

通过存档存储及加载 CObject (见前)

下面用一个示例来解释这个问题。

目标:一个画图程序,通过保存打开按钮存取图片。方法:保存图片绘制信息。按步骤:

●创建可序列化的类 ->Graph.cpp+Graph.h

●在 View 类中添加对控件的响应,实现画图功能,每次鼠标弹起的时候

保存绘图信息

●保存文件(通过 Doc 的 Serialize 来保存数据)

●打开文件(通过 Doc 的 Serialize 来读取数据,并将其重绘)

在 View 类中定义 CObArray m_obArray;

下面按这个思路来完成:(在 C Graph 子类中完成重绘的画图功能)Graph.cpp

#include"StdAfx.h"

#include"./graph.h"

IMPLEMENT_SERIAL(CGraph, CObject, 1 )

CGraph::CGraph(void)

: m_ptOrigin(0)

, m_ptEnd(0)

, m_nDrawType(0)

{

}

CGraph::CGraph(CPoint m_ptOrigin,CPoint m_ptEnd,UINT m_nDrawType)

{

this->m_ptOrigin=m_ptOrigin;

this->m_ptEnd=m_ptEnd;

this->m_nDrawType=m_nDrawType;

}

CGraph::~CGraph(void)

{

}

void CGraph::Serialize( CArchive& ar )

{

//继承基类的CObject

CObject::Serialize( ar );

if( ar.IsStoring() )

{

ar << m_ptOrigin << m_ptEnd << m_nDrawType ;

}

else

{

ar >> m_ptOrigin >> m_ptEnd >> m_nDrawType ;

}

}

void CGraph::Draw(CDC* pDC)

{

CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));

CBrush *pOldBrush=pDC->SelectObject(pBrush);

switch(m_nDrawType)

{

case 1:

pDC->SetPixel(m_ptEnd,RGB(0,0,0));

break;

case 2:

pDC->MoveTo(m_ptOrigin);

pDC->LineTo(m_ptEnd);

break;

case 3:

pDC->Rectangle(CRect(m_ptOrigin,m_ptEnd));

break;

case 4:

pDC->Ellipse(CRect(m_ptOrigin,m_ptEnd));

break;

}

pDC->SelectObject(pOldBrush);

}

Graph..h

#pragma once

#include"atltypes.h"

class CGraph : public CObject

{

public:

DECLARE_SERIAL( CGraph )

CGraph(void);

CGraph::CGraph(CPoint m_ptOrigin,CPoint m_ptEnd,UINT m_nDrawType);

void Serialize( CArchive& ar );

~CGraph(void);

CPoint m_ptOrigin;

CPoint m_ptEnd;

UINT m_nDrawType;

void Draw(CDC* pDC);

};

在 View 类中添加画图功能

void CGraphicSerialView::OnDot()

{

// TODO: 在此添加命令处理程序代码

m_nDrawType=1;

}

void CGraphicSerialView::OnLine()

{

// TODO: 在此添加命令处理程序代码

m_nDrawType=2;

}

void CGraphicSerialView::OnRectangle()

{

// TODO: 在此添加命令处理程序代码

m_nDrawType=3;

}

void CGraphicSerialView::OnEllipse()

{

// TODO: 在此添加命令处理程序代码

m_nDrawType=4;

}

void CGraphicSerialView::OnLButtonDown(UINT nFlags, CPoint point)

{

// TODO: 在此添加消息处理程序代码和/或调用默认值

m_ptOrigin = point;

CView::OnLButtonDown(nFlags, point);

}

void CGraphicSerialView::OnLButtonUp(UINT nFlags, CPoint point)

{

// TODO: 在此添加消息处理程序代码和/或调用默认值

CClientDC dc(this);

CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH)); //选择一个透明画刷

dc.SelectObject(pBrush);

switch(m_nDrawType)

{

case 1:

dc.SetPixel(point,RGB(0,0,0));

break;

case 2:

dc.MoveTo(m_ptOrigin);

dc.LineTo(point);

break;

case 3:

dc.Rectangle(m_ptOrigin.x,m_ptOrigin.y,point.x,point.y);

break;

case 4:

dc.Ellipse(CRect(m_ptOrigin,point));

break;

default:

break;

}

//将图形信息保存起来

CGraph *pGraph=new CGraph( m_ptOrigin , point , m_nDrawType ); //创建一个pGraph指针指向一个存储图形信息的“图形”

m_obArray.Add(pGraph);//将一群这样的pGraph组织在一起放进m_obArray

CView::OnLButtonUp(nFlags, point);

}

但是要保存和读取文件需要用到 Serialize

因此转到 Doc 类

void CGraphicSerialDoc::Serialize(CArchive& ar)

{

POSITION pos=GetFirstViewPosition();//获得第一个视类对象在对象列表中的位置

CGraphicSerialView *pView=(CGraphicSerialView*)GetNextView(pos);//找到当前视类对象的指针,由于这是单文档,因此只有一个视类对象

if (ar.IsStoring())

{

// TODO: 在此添加存储代码

int nCount=pView->m_obArray.GetSize();

ar<

for(int i=0;i

{

ar<m_obArray.GetAt(i);

}

}

else

{

// TODO: 在此添加加载代码

int nCount;

ar>>nCount;

CGraph *pGraph;

for(int i=0;i

{

ar>>pGraph;

pView->m_obArray.Add(pGraph);

}

}

}

但是读取数据的时候还需要重绘图像:转回View类,因为在View类加载的时候会自动调用OnDraw(),在OnDraw()中添加如下语句。

int nCount;

nCount=m_obArray.GetSize();

for(int i=0;i

{

((CGraph*)m_obArray.GetAt(i))->Draw(pDC);

}

基本上完成了通过serialize保存和打开文件。

用serialize的好处:通过缓存来保存,当缓存区满了才进行一次读/写,因此提高了应用程序的效率

另外, Archive 对象是支持序列化的,因此在读写数据的时候即可以按以上

方法在 Doc 类的 Serialize 来保存和打开数据。

因此修改 Doc 中的 Serialize 为

void CGraphicSerialDoc::Serialize(CArchive& ar)

{

POSITION pos=GetFirstViewPosition();//获得第一个视类对象在对象列表中的位置

CGraphicSerialView *pView=(CGraphicSerialView*)GetNextView(pos);//找到当前视类对象的指针,由于这是单文档,因此只有一个视类对象

if (ar.IsStoring())

{

// TODO: 在此添加存储代码

}

else

{

// TODO: 在此添加加载代码

}

pView->m_obArray.Serialize(ar); //将这个数据传递给

}

其中CObArray类对象读取数据的方法:(以下是MFC源代码,无须用户添加)void CObArray::Serialize(CArchive& ar)

{

ASSERT_VALID(this);

CObject::Serialize(ar);

if (ar.IsStoring())

{

ar.WriteCount(m_nSize);

for (INT_PTR i = 0; i < m_nSize; i++)

ar << m_pData[i];

}

else

{

DWORD_PTR nOldSize = ar.ReadCount();

SetSize(nOldSize);

for (INT_PTR i = 0; i < m_nSize; i++)

ar >> m_pData[i];

}

}

下面直接在 Doc 类中使用 CObArray 对象(取消之前定义在 View 类中的该类对象)

在 Doc 类中定义 CObArray m_obArray;

存图形数据的代码修改为:

CGraphicDoc *pDoc=GetDocument();//通过视类提供的GetDocument()方法来获得Doc类指针pDoc->m_obArray.Add(pGraph);

修改其他位置的 m_obArray

void CGraphicSerialView::OnDraw(CDC* pDC)

{

……

nCount=pDoc->m_obArray.GetSize();

for(int i=0;i

{

((CGraph*)pDoc->m_obArray.GetAt(i))->Draw(pDC); //Doc类中定义m_obArray的情况}

}

void CGraphicSerialDoc::Serialize(CArchive& ar)

{

……

m_obArray.Serialize(ar);//Doc类中定义m_obArray的情况

}

当我们新建和打开文档的时候,我们之前的文档对象并没有被销毁(系统利用OnNewDocument 方法所新建的对象)之前在堆上建立了文档对象。此时应删除文档对象。

在文档类中重载函数void CGraphicSerialDoc::DeleteContents()来删除文档对象,以避免内存泄露。

void CGraphicSerialDoc::DeleteContents()

{

int nCount;

nCount=m_obArray.GetSize();

/*for(int i=0;i

{

delete m_obArray.GetAt(i);

//m_obArray.RemoveAt(i);

}

m_obArray.RemoveAll();*/

while(nCount--)

{

delete m_obArray.GetAt(nCount);

m_obArray.RemoveAt(nCount);

}

CDocument::DeleteContents();

}

java序列化的作用

最近在阅读Core J2EE Patterns 的时候发现例子里用于在各个层次里进行传输的TO(Data Transfer Object)都实现了java.io.Serializable接口,看到这些偶突然感到茅塞顿开~困扰了很久的关于Serializable的疑问渐渐解开了,查找相关资料并总结如下: 序列化是什么: 序列化就是将一个对象的状态(各个属性量)保存起来,然后在适当的时候再获得。 序列化分为两大部分:序列化和反序列化。序列化是这个过程的第一部分,将数据分解成字节流,以便存储在文件中或在网络上传输。反序列化就是打开字节流并重构对象。对象序列化不仅要将基本数据类型转换成字节表示,有时还要恢复数据。恢复数据要求有恢复数据的对象实例 序列化的什么特点: 如果某个类能够被序列化,其子类也可以被序列化。声明为static和transient类型的成员数据不能被序列化。因为static代表类的状态, transient代表对象的临时数据。 什么时候使用序列化: 一:对象序列化可以实现分布式对象。主要应用例如:RMI要利用对象序列化运行远程主机上的服务,就像在本地机上运行对象时一样。 二:java对象序列化不仅保留一个对象的数据,而且递归保存对象引用的每个对象的数据。可以将整个对象层次写入字节流中,可以保存在文件中或在网络连接上传递。利用对象序列化可以进行对象的"深复制",即复制对象本身及引用的对象本身。序列化一个对象可能得到整个对象序列。 ====================== 可以看看接口java.io.serializable的中文解释: Serializable public interface Serializable 类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。

对象序列化实验

电子科技大学 实验报告 学生姓名:学号:指导教师: 实验地点:实验时间:2011.12.14 一、实验室名称: Linux环境高级编程实验室 二、实验项目名称: 对象序列化实验 三、实验学时: 8学时 四、实验目的: 熟悉基本的对象序列化方法 五、实验内容: 共进行5个版本的开发: ●版本1:将一个类的一个对象序列化到文件 ●版本2:将一个类的多个对象序列化到文件 ●版本3:将两个类的多个对象序列化到文件

●版本4:按照面向对象的方法,解决多个类的多个对象序列 化到文件的问题 ●版本5:序列化的目的地不仅可以是文件,还可以是其他, 即可配置性 六、实验步骤: 实验一: Test_1.cpp: #include #include #include using namespace std; //指定名字空间 class test_1 { private: int x; public: test_1() { int x = 0; } explicit test_1(int y) { x = y; } virtual ~test_1() //虚函数 { } public: void file() {

cout << "in file(): " << x << endl; } public: bool Serialize(const char *path) const //序列化部分 { int fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0); //打开experiment文件 if(-1 == fd) return false; if(write(fd, &x, sizeof(int)) == -1)//写文件 { close(fd); return false; } if(::close(fd) == -1)//关闭文件 return false; return true; } bool Deserialize(const char *path) //反序列化部分 { int fd = open(path, O_RDWR);// if(-1 == fd) return false; int red = read(fd, &x, sizeof(int));//只序列化一个值 if(-1 == red) { close(fd); return false; } if(close(fd) == -1) return false; return true; } }; int main() { { test_1 ex(1314); ex.Serialize("recored.txt"); }

C#编程实验

实验一 1. 尝试用命令行方式编译一个简单的控制台程序为可执行PE文件。 (1) 先用“记事本”编写一个简单的控制台应用程序p1.cs,该程序中只包含可供测试的几行简单代码,例如为: using System; using System.Threading; class test { static void Main() { int x, y; x=Int32.Parse(Console.ReadLine()); y=Int32.Parse(Console.ReadLine()); Console.WriteLine("{0}+{1}={2}",x, y, x+y); Console.ReadLine(); } } (2) 使用C:\Windows\https://www.doczj.com/doc/866899287.html,\Framework\v2.0.50727\csc.exe 程序(该路径为VS2005下适用,如果用更高版本时应相应调整)以及适当的参数执行编译命令。产生一个可执行PE程序。 (3) 执行该PE程序,观察是否符合预期。 (4) 观察用以上方法编译时,如果代码中有错误,系统如何输出错误信息? 2. 使用GC类控制.NET的垃圾回收操作。 (1) 按照教材上【例1-3】,建立C#的控制台应用程序。 (2) 编译调试该程序,观察、记录控制台输出。 (3) 如果要使MakeSomeGarbage方法中产生的对象不会被回收,应该如何修改MakeSomeGarbage中的代码?修改后实际运行时,观察程序输出的相关信息是否与预计一致(需要与修改前输出的内存占有数据相比较)。 3. 学习使用委托 (1) 按照教材上【例1-5】,建立C#的控制台应用程序。 (2) 编译调试该程序,观察、记录控制台输出。 4. 不要利用Visual https://www.doczj.com/doc/866899287.html, IDE环境的“工具箱”、“属性窗口”,最好只使用“笔记本”写代码,编写一个“Hello,World!”的Windows应用程序。 (1) 该Windows程序窗体上有一个按钮。当单击按钮时,弹出对话框显示“Hello,World!”。 (2) 在“命令行窗口”下执行CSC将C#代码文件编译为PE程序。 提示: 可在Form_Load等事件中执行Button button1=new Button(); 创建该按钮,对该按钮,要将其加入到Form的Controls集合中。然后对按钮的Text、Position等属性赋值。最后记得要为单击按钮的事件设置一个方法:

C语言的数据序列化

C语言的数据序列化 64位平台C/C++开发注意事项 在/en/l/上例出了28个在64位平台上使用C/C++开发的注意事项,对于进入64位时代的程序员应该去看看这28个事项,这些英文读物对于有C/C++功底的朋友读起来应该并不难,我估计大约20-30分钟可以精读完一篇(或者更快),下面是这28个注意事项的列表。相信对大家一点有

帮助。https://www.doczj.com/doc/866899287.html, Lesson01.What64-bit systems are.Lesson02.S 数据结构的序列化是个很有用的东西。这几天在修改原来的资源管理模块,碰到从前做的几个数据文件解析的子模块,改得很烦,就重新思考序列化的方案了。Java和.Net 等,由于有完整的数据元信息,语言便提供了完善的序列化解决方案。C++对此在语言设计上有所缺陷,所以并没有特别好的,被所有人接受的方案。现存的C++

serialization方案多类似于MFC在二十年前的做法。而后,boost提供了一个看起来更完备的方案 (boost.serialization)。所谓更完备,我指的是非侵入。boost的解决方案用起来感觉更现代,看起来更漂亮。给人一种不需要修改已有的C++代码,就能把本不支持serialize的类加上这个特性的心理快感。换句话说,就是这件事情我能做的,至于真正做的事情会碰到什么,那就

不得而知了。好吧,老实说,我不喜欢用大量苦力(或是高智慧的结晶?)堆积起来的代码。不管是别人出的力,还是我自己出的。另外,我希望有一个C的解决方案,而不是C++的。所以从昨天开始,就抽了点时间来搞定这件事。 问题来至于C/C++语言未提供类型元信息,那我们从根本上去解决好了。得到元信息的方案不在于使用奇怪的宏,

最新初中课题研究《主题式序列化作文教学课题实验》阶段工作总结

初中课题研究《主题式序列化作文教学课题实验》阶段工作总 结

初中课题研究《主题式序列化作文教学课题实验》阶段总结 我校自自己申报的原创课题——“主题式作文序列化教学课题实验”在山东省教科所立项以来,课题实验组老师热情饱满,态度积极,自觉加强理论学习,勇于作文教学改革实践,阶段性工作取得了一定的成效,现将本学期工作总结如下: 一、积极创设条件,进行课题申报 我校的作文教学有一定的教改基础,我校积极参与实施了淄博市体验式作文教学改革的实验,为我市作文教学改革的实验单位之一,作文教学改革取得了一定的成效,不少教师积累了一些经验,对作文教学方法的研究有了一些新的认识。如我校牟维和老师出版了作文教学专著《中学生使用话题作文指导》(延边大学出版社)牛晓彬老师获得淄博市作文竞赛辅导一等奖。牟维和老师获得淄博市体验式作文教学教学案例一等奖,我校在桓台县作文竞赛中获得全县第一名等,但不可否认的是作文教学的现状堪忧,应试作文愈演愈烈,公式化模式化、所谓的考场作文教学严重束缚了学生的个性化发展,说假话,写假事;小孩儿说大人话,毫无童心童趣;"内容空洞,不实在,不具体;一段一段甚至整篇整篇地抄写别人的作文;千人一面,没有个性和特点,究其原因,主要在:作文与学生生活、学习严重脱离,学生无内容可写,形成了"巧妇难为无米之炊"的尴尬局面;作文教学存在着"文学化"、"成人化"的倾向,使学生感到高不可攀,逐渐失去对作文的兴趣;作文教学存在着随意性及无目的、大操练的倾向,缺乏一定的训练序列。由此可见,作文教

学少了对学生主体精神的关注,写作没有成为孩子生活的真实需要。因此,我们认为应该让作文回归其本体功能――让学生在真实的生活中写作。我校的语文教师带着困惑与思考走到了一起,在淄博市教研室崔雪梅老师的直接指导下,“主题式作文序列化教学”实验课题应运而生。课题实验组人员热情高涨,积极准备。或阅读钻研理论著作,或进行调查研究,或向专家请教,或进行实验设计。2008年3月27日又召开了课题实验论证会,会上邀请了山东省初中语文教研员张伟忠老师,省教科所张斌博士作实验指导报告,与会专家提出许多指导性意见,为课题的顺利开展打下了坚实的基础。最后在学校领导的支持下,在市教研室的帮助下,“主题式作文序列化教学”课题实验的申报得以成功。 二、加强教学调查,确定实验班级与研究计划 课题的实验是建立在对教与学的基础上,其研究的根本目的是促进学生写作水平的提高,因此课题实验开始时重新对全校学生的作文现状作了全面深入的分析研究,并此基础上,确定了课题实验的年级——2006级,并召开了课题组会议,依据调查情况确定了课题研究开展的计划与方法。 三、加强课题研究中的理论学习 本课题试图通过研究,让教师在观念上确定以提高学生“观察生活,积累生活,感悟生活,表达生活”的能力为目标,“以课堂为轴心,向学生生活的各个领域开拓延展,充分利用一切可以利用的渠道和机会,发展学生作文能力”的“生活作文”教育观。教师必须更新自己

巧用三步骤助推个别化学习活动“序列化”

巧用三步骤助推个别化学习活动“序列化” 《3-6岁儿童学习与发展指南》(指南)指出:“要充分理解和尊重幼儿发展进程中的个别差异,支持和引导他们从原有水平向更高水平发展,按照自身的速度和方式到达《指南》所呈现的发展‘阶梯’,切忌用一把‘尺子’衡量所有幼儿。”所以我园针对不同发展水平的幼儿设计材料,以“序列化”的模式开展了个别化学习。在这样的学习下幼儿能自我发现、自我完善、自我学习、自我探索,它有着相对自由宽松的活动氛围,能让孩子们体验到真正的自由和自主,体验到乐趣。 一、个别化学习活动中存在的问题 1.内容无计划,盲目进行。 教师们对个别化学习的投放没有一个系统的计划,每次定学习内容都是很盲目的,这个星期定的内容也许是比上星期的要简单或者是难度大非常多的内容。 2.材料无层次,投放无序。 由于计划没有,导致做材料也是一个比较头疼的事,教师们只是看到有什么材料就投放什么材料,没有一个先后顺序。 3.观察无目的,指导单一。

幼儿在游戏进行时,教师观察不够细致。个别化游戏是班内每个孩子都参与的游戏,教师要关注到每个孩子的确很难,在这样的情况下,往往就是观察不全面、不细致、导致最后提升的学习效果不强烈。 二、“序列化”模式在个别化学习活动中的运用策略 (一)活动之前“巧”选内容,形成初步的“序列化”模式 1.以点盖全――“选”横向内容。 教师可按照自己执教的年龄孩子设定以《指南》为导向并符合他们的学习计划,使得一个一个学习计划层层递进。考虑到小班幼儿的年龄特点,我选择了糖果为主要材料。 游戏一:糖果加工厂。 准备皱纸、报纸等材料,以“糖果加工厂”的形式展开,幼儿以制作糖果的工作人员为角色,吸引孩子的参与兴趣。根据小班孩子正处于具体形象思维阶段的特点,所以在盒子上贴上制作的图示方便于每位孩子的学习。 游戏二:糖果大赢家。 利用幼儿在糖果加工厂里制作出来的糖果投放到“糖果大赢家”中,选择幼儿熟悉的动物角色,如:小兔、小狗、小猫等动物供幼儿选择。2到3个幼儿一起比赛,扔到几就取几颗糖果,最后比比谁赢得多。 游戏三:礼物大搬家。

JAVA序列化基础知识Serializable与Externalizable的区别

大家都知道Serializable是一个mark interface,告诉JVM这个对象可以被转换成二进制流来传输. 但是Serializable与Externalizable的转换二进制流的过程是不一样的. Serializable 在我们实现这个接口的时候,我们可以使用4个私有方法来控制序列化的过程: 我们来看一个例子: public class FooImpl implements java.io.Serializable{ private String message; public String getFoo() { return message; } public void setMessage(String message) { this.message = message; } private void writeObject(java.io.ObjectOutputStream out) throws IOException { System.out.println("writeObject invoked"); out.writeObject(this.message == null ? "hohohahaha" : this.message); } private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { System.out.println("readObject invoked"); this.message = (String) in.readObject(); System.out.println("got message:" + message); } private Object writeReplace() throws ObjectStreamException { System.out.println("writeReplace invoked"); return this; } private Object readResolve() throws ObjectStreamException { System.out.println("readResolve invoked"); return this; }

C++序列化

转载:C++中使用STL轻松实现序列化 2008-01-22 19:58 转自:https://www.doczj.com/doc/866899287.html,/pandaxcl/archive/2006/04/03/649682.aspx #if 0 在用C++编写应用程序的过程中,经常涉及到序列化的问题,但是序列化的问题通常都 会有非常繁琐的过程代码需要书写,本文中就是通过简单的步骤实现了程序的序列化问题 ,简单直接,和其它的序列化方案有着很大的不同。 首先来看看简单的数据写入文件和从文件读入数据的代码: 特别注解:本人特别喜欢用STL来书写代码,一方面是便于移植,但是另一方却是在于 用STL书写的代码简单直接,可读性好。如果还不熟悉STL,本文则不大适合你:) #endif #if CODE1 ///////////////////////////////////////////////////////////////////// /////////// //模拟程序序列化的简单代码 #include //cout #include //ofstream,ifstream #include //vector #include //ostream_iterator,istream_iterator,back_inserter #include //partial_sum #include //copy #include #include using namespace std;//简化代码的书写,经std名字空间成为默认名字空间int main() { {//从程序序列化到文件 vector v(5,1);//[1,1,1,1,1] partial_sum(v.begin(),v.end(),v.begin());//[1,2,3,4,5] ofstream out("data.txt");//生成文件输出流 //将数组v中的数据全部输出到文件流中,这种操作在C++中成为文件操作 //在这里暂时称为序列化到文件操作。实际上这里为了简单序列化的格式 //为文本文件格式。如果需要其它的格式完全可以通过自定义输出流游标 //的方式,或者重载运算符operator<<和operator>>实现不同的序列

对象序列化实验

电子科技大学 实验报告 学生:学号:指导教师: 实验地点:实验时间:2011.12.14 一、实验室名称: Linux环境高级编程实验室 二、实验项目名称: 对象序列化实验 三、实验学时: 8学时 四、实验目的: 熟悉基本的对象序列化方法 五、实验容: 共进行5个版本的开发: ●版本1:将一个类的一个对象序列化到文件 ●版本2:将一个类的多个对象序列化到文件 ●版本3:将两个类的多个对象序列化到文件

●版本4:按照面向对象的方法,解决多个类的多个对象序列 化到文件的问题 ●版本5:序列化的目的地不仅可以是文件,还可以是其他, 即可配置性 六、实验步骤: 实验一: Test_1.cpp: #include #include #include using namespace std; //指定名字空间 class test_1 { private: int x; public: test_1() { int x = 0; } explicit test_1(int y) { x = y; } virtual ~test_1() //虚函数 { } public: void file() {

cout << "in file(): " << x << endl; } public: bool Serialize(const char *path) const //序列化部分 { int fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0); //打开experiment文件 if(-1 == fd) return false; if(write(fd, &x, sizeof(int)) == -1)//写文件 { close(fd); return false; } if(::close(fd) == -1)//关闭文件 return false; return true; } bool Deserialize(const char *path) //反序列化部分 { int fd = open(path, O_RDWR);// if(-1 == fd) return false; int red = read(fd, &x, sizeof(int));//只序列化一个值 if(-1 == red) { close(fd); return false; } if(close(fd) == -1) return false; return true; } }; int main() { { test_1 ex(1314); ex.Serialize("recored.txt"); }

写作思维序列化训练的实践研究-开题报告

写作思维序列化训练的实践研究-开题报告

《写作思维序列化训练的实践研究》开题报告 一.课题研究背景 作文水平是语文水平的综合反映,不仅仅反映作者对已知信息的表达能力和组合技巧,而且还能反映一个人的心智水平。有一份调查报告显示:有45%的学生把作文当做一种负担,12%的学生讨厌语文。许多学生患有作文恐惧症,谈作文色变,这严重地影响着母语学习的质量。长期以来,我校广大语文教育工作者积极探索,大胆实践,勇于创新,积累了不少经验,取得了可喜的成绩。但不得不承认我们在语文教学中最薄弱的环节还是作文教学,至今仍没有走出“高耗低效”的怪圈。 普通高中语文课程标准规定:写作是运用语言文字进行书面表达和交流的重要方式,是认识世界、认识自我、进行创造性表述的过程。写作教学应着重培养学生的观察能力、想像能力和表达能力,重视发展学生的思维能力,发展创造性思维。鼓励学生自由地表达、有个性地表达、有创意地表达,尽可能减少对写作的束缚,为学生提供广阔的写作空间。”“ 高中语文课程要满足多样化和选择性的需要,必须增强课程资源意识,重视课程资源的利用和开发。语文教师应高度重视课程资源的利用与开发。” 对照课标,我们就能清楚的发现,在作文的教与学中,无论是老师还是学生存在问题的原因。 教师方面: (1)对学生的写作潜能挖掘激发的不够。作为老师,应该千方百计的唤醒、挖掘、激发学生的写作欲望,消除畏惧心理,培养写作兴趣。孔子说过:“知之者不如好之者,好之者不如乐之者。”谈得便是兴趣的问题。学生如果有了写作兴趣,把写作当作乐事,自然就会愿意写作,乐于写作了。教师在这个方面方式与方法都需要改进和提高。 (2)对教材资源的利用与开发重视程度不够。中学语文教材所选的课文都是经过时间检验的经典文章,汇聚古今中外的名篇佳作、文章精华,久经岁月磨练,历来脍炙人口。教师在教学过程中缺乏有意识的开发和利用这些资源。其实,我们每学习一篇课文,都可以把作文指导和课文教学有机结合起来,将学习写作与分析课文融会贯通,让每一篇课文都成为学生写作的练兵场。给学生提供可以参照的典型、能够模仿的范例,或积累雅词美句、或进行句式仿写、或学一点写作技巧、或模仿篇章布局、或再加工改造等。总之,让教材成为学生练习写作的蓝本,可以有效的提高学生的写作素养。 学生方面: (1)对写作素材的积累占重视程度有的不够。“巧妇难为无米之炊”,学生的心中没有材料,又怎能进行恰当的选材、组材,写出中意的文章?没有写作素材,全篇空话、套话,言之无物的现象也就不足为怪了。同学们习作时存在最普遍的问题就是无话可说。好不容易拼拼凑凑才写成一篇文章,却写得不够具体,也不真实。“问渠哪得清如许,唯有源头活水来”便是这个道理。 (2)创造力严重缺失。学生被迫按应试模式写作,以致头脑僵化、思维阻塞、文思枯竭,创造性精神被消磨,创造性思维被扼杀,并逐步形成盲目从众的思维惰性,题材雷同,矫揉造作。而长期以来,在应试教育统一化标准的束缚下,

java实验九

《Java 语言程序设计》实验报告(九) 实验名称:______________指导教师:______ _____实验日期:_________ 专 业:______________班 级:___________姓 名:_________ Java 数据流编程 张鑫 2015-12-25 电子商务 电子商务1302 李鸿儒

三、实验结果与结论:(经调试正确的源程序(核心部分)和程序的运行结果)LX5_3.java程序执行结果如图1所示: 图1 LX5_4.java程序执行结果如图2所示: 图2 LX5_5.java程序执行结果如图3所示: 图3 LX5_6.java程序执行结果如图4所示: 图4 LX10_3.java程序执行结果如图5所示: 图5 1、请设计一个从键盘输入一个数n,求n! Jiecheng.java源程序如下: import java.util.Scanner; public class Jiecheng{ public static void main(String args[]){ Scanner input=new Scanner(System.in); System.out.println("请输入数字n:"); int n=input.nextInt(); System.out.println("n!="+sum(n)); }

public static int sum(int n){ int sum=1; for(inti=1;i<=n;i++) sum*=i; return sum; } } Jiecheng.java程序执行结果如图6所示: 图6 2、写一个程序,允许用户依次输入多个姓名和住址,并能将用户的输入保存到文件中。用户输入“quit”表示输入完毕,程序退出。 Test1.java源程序如下: import java.util.Scanner; import java.io.*; public class Test1{ public static void main(String args[]){ OutputStreamos=null; OutputStreamWriterosw=null; BufferedWriterbw=null; try{ os=new FileOutputStream("test.txt"); osw=new OutputStreamWriter(os); bw=new BufferedWriter(osw); while(true){ Scanner sc=new Scanner(System.in); String str=sc.nextLine(); if(str.equals("quit"))break; bw.write(str); bw.newLine(); } }catch(IOException w){ }finally{ try{ if(bw!=null)bw.close(); }catch(IOException w){ } } } }

将php序列化到数据库的对象饭序列化成java对象

将php序列化到数据库的对象饭序列化成java对象 php的对象序列化到数据库中,形如 a:3:{i:0;i:1241;i:1;i:4;i:2;i:16;}但是java需要取出这样的对象,转换成java的对象/* PHPSerializer.java * * Author: Ma Bingyao * Copyright: https://www.doczj.com/doc/866899287.html, * Version: 2.1 * LastModified: 2006-08-09 * This library is free. You can redistribute it and/or modify it. * https://www.doczj.com/doc/866899287.html,/?p=202 */ package org.phprpc.util; import java.io.*; import java.util.*; import https://www.doczj.com/doc/866899287.html,ng.reflect.*;

class UnSerializeResult { public Object value; public int hv; public UnSerializeResult() {} public UnSerializeResult(Object value, int hv) { this.value = value; this.hv = hv; } } public class PHPSerializer { private static Package[] __packages = Package.getPackages(); private static final byte __Quote = 34; private static final byte __0 = 48; private static final byte __1 = 49; private static final byte __Colon = 58; private static final byte __Semicolon = 59; private static final byte __C = 67; private static final byte __N = 78;

vc++实验文档序列化

一、实验目的与任务 掌握文档序列化操作过程。 二、实验涉及的相关知识点 1.文档序列化包括创建空文档、打开文档、保存文档和关闭 文档; 2.Serilize函数的使用; 3.对文档模板字串资源IDR_MAINFRAME内容的含义与修 改 三、实验内容与过程 1.创建一个默认的SDI,命名为Ex_Student; 2.复制以前做好的“学生成绩输入”对话框; 3.复制“学生成绩输入”对话框类CInputDlg; 4.实现ClassWizard对CInputDlg类的支持; 5.添加一个CStudent类并使该类可序列化。打开 EX_StudentDoc.h文件,在class CEx_StudentDoc前添加代 码(附后); 6.添加并处理菜单项。在菜单资源的主菜单中添加顶层菜单 项“学生记录(&S)”,在该顶层菜单项中添加子菜单“添

加(&A)”(ID_STUREC_ADD),并为其添加COMMAND 消息代码(附后); 7.修改CEx_StudentDoc类代码(附后); 8.修改CEx_StudentView类代码(附后); 9.修改文档的字串资源为: EX_CtrlStudent\nSrudentRec\nEX_CtrlStudent\n记录文件 (*.rec)\n.rec\nEXCtrlStudent.Document\nEX_CtrlStudent.Do cument 10.添加一个可序列化类CStuHeader类在Ex_StudentDoc.h文 件中(代码附后); 11.修改Ex_StudentDoc::Serialize代码(附后); 12.编译运行并测试。 四、实验结果及分析 运行后点击菜单栏的“学生记录”下拉列表的“添加”选项,弹出“学生成绩输入”对话框,输入信息点击确认,输入信 息便显示在试图窗口。再次执行上述过程,视图窗口里便追 加一条记录。单击“保存”,可以将信息以指定格式存储。打 击“打开”,可将存储信息重新显示在视图窗口里。

Java-Jackson反序列化漏洞及挖洞思路

源码分析Jackson反序列化漏洞 前言: 本次分析从Java序列化和反序列化源码开始分析,进一步分析Jackson源码,找出造成漏洞的原因,最后以Jackson2.9.2版本,JDK1.80_171,resin4.0.52,CVE-2020-10673为例复现漏洞。 一.JA V A反序列化原理 1.1 Class对象 每一个类都有一个Class对象,Class对象包含每一个类的运行时信息,每一个类都有一个Class对象,每编译一个类就产生一个Class对象,Class类没有公共的构造方法,Class对象是在类加载的时候由JVM以及通过调用类加载器中的DefineClass()方法自动构造的,因此不能显式地声明一个Class对象。在类加载阶段,类加载器首先检查这个类的Class对象是否已经被加载。如果尚未加载,默认的类加载器就会根据类的全限定名查找.class文件。一旦某个类的Class对象被载入内存,我们就可以它来创建这个类的所有对象以及获得这个类的运行时信息。 获得Class对象的方法: 1).Class.forName(“类的全名”);//com.xx.xx.xx 2).实例对象.getClass() 3).类名.class 1.2反射 JA V A反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

实现Java反射机制的类都位于https://www.doczj.com/doc/866899287.html,ng.reflect包中: 1).Class类:代表一个类 2).Field类:代表类的成员变量(类的属性) 3).Method类:代表类的方法 4).Constructor类:代表类的构造方法 5).Array类:提供了动态创建数组,以及访问数组的元素的静态方法 简单反射调用代码 Class clz=this.getClass(); Object obj= clz.getMethod("方法名",Class对象序列).invoke(this,Object参数序列); 1.3 反序列化 Java 序列化是指把Java 对象转换为字节序列的过程便于保存在内存、文件、数据库中,ObjectOutputStream类的writeObject() 方法可以实现序列化。 Java 反序列化是指把字节序列恢复为Java 对象的过程,ObjectInputStream 类的readObject() 方法用于反序列化。 RMI:是Java 的一组拥护开发分布式应用程序的API,实现了不同操作系统之间程序的方法调用。值得注意的是,RMI 的传输100% 基于反序列化,Java RMI 的默认端口是1099 端口。 JMX:JMX 是一套标准的代理和服务,用户可以在任何Java 应用程序中使用这些代理和服务实现管理,中间件软件WebLogic 的管理页面就是基于JMX 开发的,而JBoss 则整个系统都基于JMX 构架。 只有实现了Serializable接口的类的对象才可以被序列化,Serializable 接口是启用其序列化功能的接口,实现java.io.Serializable 接口的类才是可序列化的,没有实现此接口的类将不能使它们的任一状态被序列化或逆序列化。 readObject() 方法的作用正是从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回,readObject() 是可以重写的,可以定制反序列化的一些行为。 readObject()主要做的事情,其实就是读取正常应该被序列化的字段信息后,

java序列化原理与算法

Java序列化原理和算法 总结: java中序列化算法的顺序: 1、子类的类信息描述 2、子类的字段信息描述(如果遇到类对象的属性,暂时用string的指针表示) 3、父类的类信息描述 4、父类的字段信息描述 5、对父类的字段信息进行赋值 6、对子类的字段信息进行赋值 7、发现子类的字段为类对象时,描述该类对象,并查找该类对象的父类,以以上方式描述,然后赋值。 本文讲解了Java序列化的机制和原理。从文中你可以了解如何序列化一个对象,什么时候需要序列化以及Java序列化的算法。 有关Java对象的序列化和反序列化也算是Java基础的一部分,下面对Java序列化的机制和原理进行一些介绍。 Java序列化算法透析 Serialization(序列化)是一种将对象以一连串的字节描述的过程;反序列化deserialization 是一种将这些字节重建成一个对象的过程。Java序列化API提供一种处理对象序列化的标准机制。在这里你能学到如何序列化一个对象,什么时候需要序列化以及Java序列化的算法,我们用一个实例来示范序列化以后的字节是如何描述一个对象的信息的。 序列化的必要性 Java中,一切都是对象,在分布式环境中经常需要将Object从这一端网络或设备传递到另一端。 这就需要有一种可以在两端传输数据的协议。Java序列化机制就是为了解决这个问题而产生。如何序列化一个对象 一个对象能够序列化的前提是实现Serializable接口,Serializable接口没有方法,更像是个标记。 有了这个标记的Class就能被序列化机制处理。 import java.io.Serializable; class TestSerial implements Serializable { public byte version = 100; public byte count = 0; } 然后我们写个程序将对象序列化并输出。ObjectOutputStream能把Object输出成Byte流。 我们将Byte流暂时存储到temp.out文件里。 public static void main(String args[]) throws IOException { FileOutputStream fos = new FileOutputStream("temp.out");

数据的序列化

1.为什么要序列化 回答: 我们在开发基于单文档的SDI程序的时候,对于文档/视图机制中的数据交换有了一定的了解。大体的流程是。文档类负责处理一些数据,然后通过调用UpdateAllViews函数通知视图类。然后视图类通过获得指向文档类的指针,来获取文档类的实时更新的数据,并且在相应的视图类里面调用相关函数完成一定的功能。 但是,我们始终没有触及到文档类与外部数据的机制,比如菜单里面的新建,打开,保存等选项,这些选项就是用来与外部数据打交道的。那么,这样文档类与外部数据到底该如何实现交换呢,以及当前程序里面的数据是否具有可持续功能,这就要用到序列化的思想了。 为了下面的讲解方便,我们仍然采用上一讲的分割视图的范例程序 Ex_MultiView_交互 2为该工程创建一个可序列化的类 ⑴点击菜单中Insert –>New Class,并且命名以及基类选择如下(必须选择基类为CObject类)

⑵为新建的类添加成员变量以及支持序列化的相关功能。 CStudent类的头文件Student.h class CStudent : public CObject { public: CStudent(CString num,CString name,CString magor,CString home); CStudent(); CStudent(CStudent &stu); void GetData(CString &num,CString &name,CString &magor,CString &home); CStudent& operator=(CStudent stu); virtual ~CStudent(); DECLARE_SERIAL(CStudent); virtual void Serialize(CArchive &ar); private: CString m_strName; CString m_strNum; CString m_strMagor; CString m_strHome; }; CStudent类的源文件Student.cpp IMPLEMENT_SERIAL(CStudent,CObject,1) CStudent::CStudent() { } CStudent::CStudent(CString num,CString name,CString magor,CString home) { m_strName = name; m_strNum = num; m_strMagor = magor; m_strHome = home; } CStudent::CStudent(CStudent &stu) { m_strName = stu.m_strName; m_strNum = stu.m_strNum; m_strMagor = stu.m_strMagor;

(1969186)JAVA 面向对象程序设计实验指导书2014级20150124

《Java面向对象程序设计》 实验指导书 (自编教材) 课程代码:1969186 开课院(系)、实验室:华信软件学院实训C509 适用专业:软件工程

实验一数组与类的定义 预习要求:复习Java的两种程序流程结构:分支结构和循环结构;数组的定义、初始化、和使用。初步编好实验程序。 一、实验目的与要求 1、熟悉Java类、对象和方法的一般操作练习等。 2、熟悉数组等的定义和使用。 二、实验内容及步骤 1. 编写Java小应用程序, 程序中自定义一个方法: double find2(int n)方法的功能是求2的n次方。 程序中调用该方法,输出2的40次方的结果并输出。 2.编写Java应用程序, 自定义类Car,类中有4个属性: String name,表示汽车的品牌; String color,表示汽车的颜色; double weight,表示汽车的自重; int price,表示汽车的价格。 要求: 1)在应用程序中创建类Car的4个对象,并通过键盘输入,初始化4个对 象的值,保存在一个数组中。 2)按价格从大到小输出4辆车的信息! 三、实验总结 1)提交实验代码 2)实验过程中的问题以及解决方法分析 3)编写实验报告,在下一次上实验课时提交。

实验二类、对象基础知识 预习要求:复习类的定义;对象和引用变量之间的关系;方法的参数传递和重载;如何使用访问控制符来设计封装良好的类;继承、组合两种类复用机制及各自的优缺点和适用场景。初步编好实验程序。 一、实验目的 1、熟练掌握类、对象的的概念以及对事物的抽象。 2、熟练掌握成员、方法的概念以及构造方法的概念。 3、熟练掌握封装性,多态性的概念 4、理解面向对象的程序设计方法。 二、实验内容与要求 1、定义一个类实现银行帐户的概念,包括的变量有"帐号"和"存款余额",包括的方法有"存款"、"取款"、"查询余额"和”显示帐号”,。定义主类,创建帐户类的对象,并完成相应操作。 提示:关键代码如下: public int getleftmoney(){ return leftmoney; } public void savemoney(double money){ leftmoney+=money; } public void getmoney(double money){ if(money<=leftmoney) leftmoney-=money; else System.out.println("只能取:"+leftmoney); } … bankaccount ba=new bankaccount(888123,1000); ba.savemoney(21000); System.out.println("存入21000元后余额为:"+ba.getleftmoney()); ba.getmoney(11500);

相关主题
文本预览
相关文档 最新文档