将C#对象保存到文件中

3
我需要实现一个新的会员申请,但不能使用数据库。我计划创建一个类来定义每个成员,其中包括姓名、部门等字段。我希望将这些成员的列表保存到文件中(不是纯文本)。所以我的问题是如何将类对象保存到文件中?
谢谢!:)

2
我看不到问题,尽管我读了它两次 - gdoron
也许是序列化和StreamWriter? - Goanne
@gdoron 是的,我也读了,发现有些困惑,抱歉我的错 :) 已经编辑过了 :) - Ahmed Mohamed
@Goanne 我知道我会使用序列化,但我不知道如何使用它?我搜索了一些资料,但我还是无法完全理解它的工作原理。 - Ahmed Mohamed
1
我希望你不要期望有很多成员,否则你的平面文件会变得非常大。 - Simon Whitehead
显示剩余2条评论
3个回答

7
我建议进行JSON或XML序列化,然后使用某种算法加密内容。我不会选择二进制序列化,因为当您需要更改程序集版本时,它并不是很友好。
我正在使用以下代码与Newtonsoft.Json(可以在NuGet上获取)一起完成此操作:
using System.IO;
using System.Security.Cryptography;
using System.Text;

using Newtonsoft.Json;

class SecureJsonSerializer<T>
    where T : class
{
    private readonly string filePath;

    private readonly ICryptoTransform encryptor;

    private readonly ICryptoTransform decryptor;

    private const string Password = "some password";

    private static readonly byte[] passwordBytes = Encoding.ASCII.GetBytes(Password);

    public SecureJsonSerializer(string filePath)
    {
        this.filePath = filePath;
        var rmCrypto = GetAlgorithm();
        this.encryptor = rmCrypto.CreateEncryptor();
        this.decryptor = rmCrypto.CreateDecryptor();
    }

    private static RijndaelManaged GetAlgorithm()
    {
        var algorithm = new RijndaelManaged();
        int bytesForKey = algorithm.KeySize / 8;
        int bytesForIV = algorithm.BlockSize / 8;
        algorithm.Key = key.GetBytes(bytesForKey);
        algorithm.IV = key.GetBytes(bytesForIV);
        return algorithm;
    }

    public void Save(T obj)
    {
        using (var writer = new StreamWriter(new CryptoStream(File.Create(this.filePath), this.encryptor, CryptoStreamMode.Write)))
        {
            writer.Write(JsonConvert.SerializeObject(obj));
        }
    }

    public T Load()
    {
        using (var reader = new StreamReader(new CryptoStream(File.OpenRead(this.filePath), this.decryptor, CryptoStreamMode.Read)))
        {
            return JsonConvert.DeserializeObject<T>(reader.ReadToEnd());
        }
    }
}

难道没有任何本地的.NET方法可以在不使用第三方插件的情况下完成吗?我倾向于不使用外部类。 - Ahmed Mohamed
同时,我不需要完整的加密功能,只是希望有一种可靠的方式来保存和加载数据。 - Ahmed Mohamed
1
最初你在你的问题中提到了加密,这就是我发表这篇文章的原因。是的,你可以使用XmlSerializer。以下是一个使用它的示例:http://www.jonasjohn.de/snippets/csharp/xmlserializer-example.htm - Martynas
这正是我正在寻找的!非常感谢 :) 编辑:至于加密,我认为它不值得,但那段代码和JSON.NET仍然非常有价值。再次感谢 :) - Ahmed Mohamed
@Martynas,密码放在哪里?你只是声明并初始化了它以及字节表示。 - Mc Midas

2
听起来你需要使用BinaryFormatter,这个工具可以将数据保存为不可读的二进制文件。相比于XmlSerialization,它的一个主要优点是你的属性不需要是公共的。
然而,我个人并不建议你采用这种方法。我自己曾经尝试过,虽然短期内很容易实现,但长期来看会带来很多麻烦。
你将面临大量的版本兼容性问题。每当你想更新任何对象(比如添加一个新属性),你都需要转换所有文件。
更糟糕的是,如果你想在同一个应用程序中进行操作,你需要同时拥有两个定义。这会导致荒谬的类定义,例如:
// my original object
class SavedObject
{
    public string Data{get;set}
}

// needed to add a field for last edit
class SavedObject2
{
    public DateTime LastEdit{get;set;}

    public SavedObject2(SavedObject so){}
}

// need a small restructure so we can now have multiple datas
// 'data' is now obsolete
class SavedObject3
{
    public List<string> DataList{get;set;}
    public SavedObject3(SavedObject2 so){}
}

使用序列化作为持久性手段只适用于两种情况。一是您知道数据定义永远不会改变(非常罕见);二是您只是以原始方式保存数据(例如仅一个字符串集合,然后代码将其转换为类)。
我强烈建议使用数据库。如果您不喜欢大多数生产数据库带来的管理工作,请考虑使用Sqlite,它小巧、便携,并且非常容易嵌入应用程序中。

我曾经认为二进制格式化可以解决我的问题 :) 感谢提供代码。至于SQLite,它需要运行SQL Server,是吗? - Ahmed Mohamed
1
没有内嵌且可移植的SqlLite。它完全不需要SqlServer。它保存到本地文件并存在于一个单独的.dll中。这就是为什么它非常适合小型嵌入式应用程序的原因。 - Quibblesome
值得一试和涉猎。非常感谢 :) - Ahmed Mohamed

0

首先,您可以使用此工具将类序列化为JSON:Json Net

其次,从您的偏好中找到任何加密工具,有很多选择,这是一个例子:Encode to 64

之后,您可以保存您的文件:

    System.File.WriteAllText(@"C:\file.dat","encripted string");

3
编码不等于加密 :) - dbones
我的错,哈哈哈,你是对的。 - Camilo Aguilar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接