2013-02-24 3 views
2

Я должен реализовать новое приложение-член без использования баз данных. Я планирую создать класс для определения каждого члена с полями, определяющими имя, отдел и т. Д. Я хочу сохранить список этих членов в файл (не простой текст). Итак, мой вопрос заключается в том, как сохранить объект класса в файл?Сохранение объекта C# в файл

Заранее спасибо :)

+2

Я не вижу вопроса здесь, хотя я читал его ** дважды **! – gdoron

+0

возможно Сериализация и StreamWriter? – Goanne

+0

@gdoron Да, я тоже это прочитал и нашел, что это сбивает с толку, извините, мой плохой :) просто отредактировал его :) –

ответ

6

Я предложил бы делать 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()); 
     } 
    } 
} 
+0

Нет ли родного .NET-способа сделать это без каких-либо сторонних аддонов? Я склонен не использовать внешние классы. –

+0

Также я не хочу полноценного шифрования, просто надежный способ сохранить и загрузить данные. –

+1

Первоначально у вас было шифрование в вашем вопросе, поэтому я разместил это. Да, вы можете использовать XmlSerializer. Вот пример использования: http://www.jonasjohn.de/snippets/csharp/xmlserializer-example.htm – Martynas

0

Ну первым можно сериализовать класс JSon с помощью этого инструмента: Json Net

Во-вторых найти любой инструмент шифрования от ваших предпочтений, есть много, вот и пример: Encode to 64

После этого вы можете сохранить файл:

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

Кодирование не шифруется :) – dbones

+0

Мой плохой хахаха ты прав –

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){} 
} 

Serialising как средство упорства хорошо только в двух сценариях. Один, где вы знаете , данные никогда не будут меняться в определении (невероятно редко) и: два, где вы просто сохраняете данные примитивным способом (например, просто набор строк, которые затем преобразуются в классы).

Я серьезно рассмотрел бы использование базы данных. Если вы не обращаете внимания на административные обязанности, которые приходят с большинством баз данных, то рассмотрите возможность использования Sqlite, он небольшой, переносимый и очень простой для встраивания в приложение.

+0

Я действительно думал, что двоичное форматирование решит мою проблему :) Спасибо за код. Что касается SQLite, для этого требуется запустить SQL Server, не так ли? –

+1

Нет SqlLite встроен и переносится. Он вообще не требует SqlServer. Он сохраняет локальный файл и существует в одной .dll. Именно поэтому он отлично подходит для небольших встроенных приложений. – Quibblesome

+0

Стоит попробовать и заняться. Большое спасибо :) –

Смежные вопросы