当前位置:天才代写 > tutorial > C语言/C++ 教程 > 实例理会C++/CLI的串行化

实例理会C++/CLI的串行化

2017-11-07 08:00 星期二 所属: C语言/C++ 教程 浏览:528

副标题#e#

串行化可使工具被转换为某种外部的形式,好比以文件存储的形式供措施利用,或通过措施间的通讯发送到另一个处理惩罚进程。转换为外部形式的进程称为"串行化",而逆进程称为"反串行化"。

简介

请看例1中的示例,其将多个工具范例的值写入到一个新的磁盘文件中,封锁文件,接着再把这些值从头读取到内存中。

例1:

using namespace System;
using namespace System::IO;
using namespace System::Runtime::Serialization::Formatters::Binary;
int main()
{
  array<int>^ intArray = {10, 20, 30};
  array<float,2>^ floatArray = {
   {1.2F, 2.4F},
   {3.5F, 6.8F},
   {8.4F, 9.7F}
  };
  DateTime dt = DateTime::Now;
  Console::WriteLine("dt >{0}<", dt);
  /*1*/ BinaryFormatter^ formatter = gcnew BinaryFormatter;
  //将数据串行化到一个文件
  /*2*/ Stream^ file = File::Open("Sr01.ser", FileMode::Create);
  /*3a*/ formatter->Serialize(file, "Hello");
  /*3b*/ formatter->Serialize(file, intArray);
  /*3c*/ formatter->Serialize(file, floatArray);
  /*3d*/ formatter->Serialize(file, true);
  /*3e*/ formatter->Serialize(file, dt);
  /*3f*/ formatter->Serialize(file, 1000);
  /*3g*/ formatter->Serialize(file, L'X');
  /*3h*/ formatter->Serialize(file, 1.23456F);
  /*4*/ file->Close();
  //从文件中反串行化数据--即读取数据
  /*5*/ file = File::Open("Sr01.ser", FileMode::Open);
  /*6a*/ String^ s = static_cast<String^>(formatter->Deserialize(file));
  Console::WriteLine("String >{0}<", s);
  /*6b*/ array<int>^ newIntArray =
  static_cast<array<int>^>(formatter->Deserialize(file));
  Console::WriteLine("newIntArray:");
  for (int i = 0; i < newIntArray->Length; ++i)
  {
   Console::Write(" {0}", newIntArray[i]);
  }
  Console::WriteLine();
  /*6c*/ array<float,2>^ newFloatArray =
  static_cast<array<float,2>^>(formatter->Deserialize(file));
  Console::WriteLine("newFloatArray:");
  for (int i = 0; i < 3; ++i)
  {
   for (int j = 0; j < 2; ++j)
   {
    Console::Write(" {0}", newFloatArray[i,j]);
   }
   Console::WriteLine();
  }
  /*6d*/ bool b = static_cast<bool>(formatter->Deserialize(file));
  Console::WriteLine("bool >{0}<", b);
  /*6e*/ DateTime newDT = static_cast<DateTime>(formatter->Deserialize(file));
  Console::WriteLine("newDT >{0}<", newDT);
  /*6f*/ int v = static_cast<int>(formatter->Deserialize(file));
  Console::WriteLine("int >{0}<", v);
  /*6g*/ wchar_t c = static_cast<wchar_t>(formatter->Deserialize(file));
  Console::WriteLine("wchar_t >{0}<", c);
  /*6h*/ float f = static_cast<float>(formatter->Deserialize(file));
  Console::WriteLine("float >{0}<", f);
  /*7*/ file->Close();
}


#p#副标题#e#

在标志1中,我们界说了一个BinaryFormatter范例的变量,此种范例的任意工具都可以二进制的形式举办串行与反串行化。

在标志2中,用指定的名称建设了一个新的文件,后缀 .ser没有出格的意思,这是约定俗成的暗示这是一个串行化数据文件。从标志3a至3h,暗示一个工具被串行化至文件中。在字符串的环境下,每个字符都被写入;在数组的环境下,所有元素都被写入;在日期时间的环境下,范例中包括的所有数据及有关依赖项都被写入;在为原始范例值的环境下,它们先被装箱,然后对应的工具被写入。上述行动中,串行化只需要吸收一个Object^范例参数的工具即可。

通过挪用Deserialize函数,可取回串行化后的数据,如标志6a中所示;因为此函数返回一个Object^范例的值,所以需要把它转换为相应的值。措施的输出如插1所示:

插1:例1中串行化、反串行化的输出

String >Hello<
newIntArray
10 20 30
newFloatArray:
1.2 2.4
3.5 6.8
8.4 9.7
bool >True<
newDT >9/29/2005 3:25:44 PM<
int >1000<
wchar_t >X<
float >1.23456<

串行化包括引用的工具

在前一个例子中,我们对相关范例举办了简朴的读写。那么,假如一个工具中包括了其他工具的句柄呢?试想有一个高出两万字的字典,存储在一个能通过键值索引的荟萃中,而在尺度模板库中,就提供了一个这样的荟萃–哈希表(Hashtable),如例2中所示:

例2:

#p#分页标题#e#

using namespace System;
using namespace System::IO;
using namespace System::Collections;
using namespace System::Runtime::Serialization::Formatters::Binary;
int main()
{
  /*1*/ Hashtable^ dictionary = gcnew Hashtable(21000);
  StreamReader^ inStream = File::OpenText("dictionary.txt"); //打开字典文件
  String^ str;
  while ((str = inStream->ReadLine()) != nullptr)
  {
   /*2*/ dictionary->Add(str, nullptr);
  }
  inStream->Close();
  /*3*/ Console::WriteLine("Dictionary contains {0} entries", dictionary->Count);
  BinaryFormatter^ formatter = gcnew BinaryFormatter();
  Stream^ file = File::Open("dictionary.ser", FileMode::Create);
  /*4*/ formatter->Serialize(file, dictionary);
  file->Close();
}

#p#副标题#e#

在标志1中,我们先分派了一个初始化为21000个条目标哈希表(这样做只是为了加速处理惩罚速度,在条目相加时不需要从头举办分派),接着从一个文本文件中,一次一行地读入字,并将其添加到标志2的哈希表中。请留意,在界说中,哈希表的每个条目都由(键/值)对构成。但在我们的措施中,键也是值,所以在第二个参数中利用了nullprt。

哈希表中的键值必需是独一的,而添加进来的任何范例的工具都必需重载System::工具名 GetHashCode函数–字符串也一样。

一旦文件中所有的字被读取并添加到哈希表中,就可通过一个简朴的Serialize挪用,把哈希表写到磁盘上,如标志4所示。在例3中,我们读入这个字典,并在个中查找用户提供的字,插2是对应的输出。

例3:

using namespace System;
using namespace System::IO;
using namespace System::Collections;
using namespace System::Runtime::Serialization::Formatters::Binary;
int main()
{
  BinaryFormatter^ formatter = gcnew BinaryFormatter;
  Stream^ file = File::Open("dictionary.ser", FileMode::Open);
  /*1*/ Hashtable^ dictionary = static_cast<Hashtable^>(formatter->Deserialize(file));
  file->Close();
  /*2*/ Console::WriteLine("Dictionary contains {0} entries", dictionary->Count);
  String^ word;
  while (true)
  {
   Console::Write("Enter a word: ");
   word = Console::ReadLine();
   if (word == nullptr)
   {
    break;
   }
   /*3*/ Console::WriteLine("{0}{1} found", word, (dictionary->Contains(word) ? "" : " not"));
  }
}

#p#副标题#e#

插2:利用反串行化举办字典查找

Dictionary contains 20159 entries
Enter a word: house
house found
Enter a word: houses
houses not found
Enter a word: brick
brick found
Enter a word: manly
manly not found

此处最重要的是,我们能在单个函数挪用中,串行、反串行化任意巨细、任意巨大性的工具。

处理惩罚多个句柄

当我们通报一个工具的句柄给Serialize时,好像会在底层对工具举办一个复制,那么,实际环境真的是这样吗?假设我们把包括有多个句柄的一个工具写入到其他工具中,可能我们挪用Serialize两次,每次都给它同一个工具的句柄呢?我们真的想获得同一工具的多个副本吗?在例4中演示了这个进程:

例4:

using namespace System;
using namespace System::IO;
using namespace System::Runtime::Serialization::Formatters::Binary;
/*1*/ [Serializable] ref class Employee { /* ... *

 

    关键字:

天才代写-代写联系方式