如何在 C++/CLI 或 C# 中将静态结构数据保存到二进制文件
Posted
技术标签:
【中文标题】如何在 C++/CLI 或 C# 中将静态结构数据保存到二进制文件【英文标题】:How to save static struct data to binary file in c++/CLI or C# 【发布时间】:2016-03-14 09:42:34 【问题描述】:我想在关闭程序时保存数据并在打开程序时加载数据。 我的结构是这样的
public ref class FormConfig
// Connect form
public:
static Int32 Connect_SlaveNo = 0; // + 1 // Axes number
static Int32 Connect_BaudrateNo = 0;
static Int32 Connect_PortNo= 0; // port number
static bool Connect_DemoCheck = false;
static String^ Connect_ConnectInfo = String::Empty;
;
我尝试将我的 static 结构数据读/写到二进制文件,但没有成功。 我认为要读/写,需要将静态结构转换为字节数组。我也使用了序列化,但它不能与静态结构一起使用。
我也尝试过单例而不是静态结构,但我遇到了与这个问题How to do singleton serialization in C#? 相同的问题。
使用非托管C++,一切都像这样非常简单,但不能在.Net中使用。
struct Medicazos m = "Bob", "Password", "Feet", 123, 456;
FILE* f = fopen(...);
fwrite(&m, sizeof(struct Medicazos), 1, f);
谁能帮帮我?
【问题讨论】:
看this 感谢您的建议。我知道序列化静态结构时没有任何意义。但我不知道如何将结构的静态数据保存到二进制文件:/ 【参考方案1】:嗯...一种方法是不要在结构中使用static
字段。为什么不创建一个包含单个结构实例的静态字段呢?还是一开始就避免使用静态?
无论如何,您始终可以编写自己的序列化方法。就这么简单(在 C# 中,因为那是我更流利的,你也注意到了 C#):
public class MyClass
public static int Field1;
public static int Field2;
public static byte[] SerializeStatics()
using (var ms = new MemoryStream())
using (var bw = new BinaryWriter(ms))
bw.Write(Field1);
bw.Write(Field2);
return ms.ToArray();
反序列化是相同的——在这个例子中只使用BinaryReader
和ReadInt32
。
此外,一些序列化程序确实支持静态属性,您通常只需将它们标记为显式序列化即可。默认值非常有意义 - 您正在序列化一个实例,包含静态类数据有什么意义?
对于风格说明:同样,这可能只是意味着您使用 static
的方式与您在其他环境或语言中习惯的方式相同,但在 C++/CLI 或 C# 中有更好的方法。 static
s 倾向于在 .NET 中避免使用(实际上,许多现代编程方法),主要的例外是缓存的各种示例。 static
s 的主要缺点是它有效地扩展了应用程序中每一行代码的状态(以及任何其他可以引用您的应用程序的人),这反过来又是常见的错误来源。您通常希望保持状态尽可能小,而是依赖参数和返回值 - 例如,当您开始使用多线程和托管环境时,这尤其有用。
【讨论】:
非常感谢您的评论。我序列化了静态结构,因为我想将该数据保存到二进制文件中。手动序列化方法可能不适合具有多种类型字段的 struct。由于二进制读取器需要知道结构中字段的类型,因此反序列化会出现问题。您关于静态的注释非常有用。但是我想知道如何在没有静态类和单例的情况下在 .Net 中使用诸如全局变量之类的东西? 他/她的建议之一是创建一个结构类型的全局变量,然后包含实例(非静态)字段。然后你应该能够序列化该结构。 @chinhngo 为什么没有单例?这是做你想做的事情的方法之一,它允许你很好地使用序列化。为什么要将它作为“全局变量”呢?通常,全局变量会使您的程序更难推理。拥有全局变量(而不是变量)可能很好,但这似乎不是你的情况。您总是有一些合理的上下文可以拥有这些值,那么为什么不使用它呢?或者也许使用依赖注入之类的东西来处理数据应该可用的地方。 谢谢@Luaan,我用的是singleton,问题解决了。【参考方案2】:两天后,我找到了解决问题的方法,希望对您有所帮助。
使用Singleton
代替static struct
。
我的代码是用 C++/CLI 编写的
保存到二进制文件
#include "stdafx.h"
using namespace System;
using namespace System::IO;
using namespace System::Collections;
using namespace System::Runtime::Serialization::Formatters::Binary;
using namespace System::Runtime::Serialization;
[Serializable]
public ref class Singleton
public:
String^ str1;
String^ str2;
Int32 num;
public:
// Private constructor allowing this type to construct the singleton.
Singleton()
// Do whatever is necessary to initialize the singleton.
str1 = "2222";
num =12345;
public:static Singleton^ theInstance ;
public: static property Singleton^ Instance
Singleton^ get()
if (theInstance == nullptr)
theInstance = gcnew Singleton();
return theInstance;
;
int main()
FileStream^ fs = gcnew FileStream( "C:\\DataFile.dat",FileMode::OpenOrCreate );
Singleton^ a = Singleton::Instance;
Console::WriteLine( "Reason: 0",a->str1);
BinaryFormatter^ formatter = gcnew BinaryFormatter;
formatter->Serialize(fs, a);
fs->Close();
return 0;
要从二进制文件中读取,只需更改 Main()
int main()
Singleton^ a = Singleton::Instance;
FileStream^ fs1 = gcnew FileStream( "C:\\DataFile.dat",FileMode::Open ); //
System::IO::FileInfo ^_FileInfo = gcnew System::IO::FileInfo("C:\\DataFile.dat");
fs1->Position =0;
BinaryFormatter^ formatter1 = gcnew BinaryFormatter;
Singleton^ b = safe_cast<Singleton^>(formatter1->Deserialize(fs1));
fs1->Close();
Console::WriteLine( "result: 0", b->str1 );
return 0;
【讨论】:
以上是关于如何在 C++/CLI 或 C# 中将静态结构数据保存到二进制文件的主要内容,如果未能解决你的问题,请参考以下文章
将 C# 对象(包含静态对象成员)作为参数传递给 C++/CLI 程序
如何在不同线程的 C++/CLI 中将图像数据从 BitmapSource (WPF) 复制到 cv::Mat (OpenCV)?