Feedback

C# - Laden und speichern von komprimierten Binärdaten

Veröffentlicht von am 8/18/2009
(1 Bewertungen)
Dieses Snippet vereinfacht das Laden und Speichern von beliebigen Daten in komprimierter, binärer Form.
Ein Demo steht im XML-Kommentar der BinaryFileIO-Klasse.
using System;
using System.Diagnostics.Contracts;
using System.IO;
using System.IO.Compression;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Permissions;

namespace Cyrons
{
   /// <summary>
   /// Bietet Funktionalität für das einfache Laden und Speichern
   ///  von beliebigen Daten in komprimierter, binärer Form.
   /// </summary>
   /// <example>
   /// <code>
   /// <![CDATA[
   ///using System;
   ///
   ///namespace CompressorDemo
   ///{
   ///   [Serializable]
   ///   public class DemoDTO
   ///   {
   ///      // Ein paar Demodaten mit verchiedenen Typen.
   ///      public Guid ID { get; set; }
   ///      public string Vorname { get; set; }
   ///      public string Nachname { get; set; }
   ///      public DateTime Geburtstag { get; set; }
   ///   }
   ///}
   ///
   /// ]]>
   /// </code>
   /// </example>
   /// /// <example>
   /// <code>
   /// <![CDATA[
   ///using System;
   ///using System.IO;
   ///using Cyrons;
   ///
   ///namespace CompressorDemo
   ///{
   ///   internal class Program
   ///   {
   ///      static void Main()
   ///      {
   ///         string fullFilename = GetProjectPath(EnvironmentMode.Regular) + @"\Demodaten.bin";
   ///
   ///         // Der Backslash wird automatisch eingesetzt.
   ///         var compressor =
   ///            new CompressedBinaryFileIO(GetProjectPath(EnvironmentMode.Regular), "Demodaten", "bin");
   ///
   ///         //======================================================================
   ///
   ///         SaveDemo(compressor);
   ///
   ///         //======================================================================
   ///
   ///         Console.WriteLine("Now trying to load and decompress...");
   ///         LoadDemo(compressor, fullFilename);
   ///
   ///         //======================================================================
   ///
   ///         // Verhindert das selbsttätige Schließen des Konsolenfensters.
   ///         Console.WriteLine("\nPress any key to terminate the program.");
   ///         Console.ReadKey();
   ///      }
   ///
   ///      private static void LoadDemo(CompressedBinaryFileIO compressor, string fullFilename)
   ///      {
   ///         if(File.Exists(fullFilename))
   ///         {
   ///            try
   ///            {
   ///               DemoDTO oldData = compressor.Load() as DemoDTO;
   ///
   ///               if(oldData == null)
   ///                  Console.WriteLine("Keine Daten zur Verarbeitung vorhanden.");
   ///               else
   ///               {
   ///                  Console.WriteLine("ID: {0}", oldData.ID);
   ///                  Console.WriteLine("Vorname: {0}", oldData.Vorname);
   ///                  Console.WriteLine("Nachname: {0}", oldData.Nachname);
   ///                  Console.WriteLine("Geburtstag: {0}", oldData.Geburtstag);
   ///               }
   ///            }
   ///            catch(Exception problem)
   ///            {
   ///               Console.WriteLine(problem);
   ///            }
   ///         }
   ///         else
   ///            Console.WriteLine("Das File existiert nicht.");
   ///      }
   ///
   ///      private static void SaveDemo(CompressedBinaryFileIO compressor)
   ///      {
   ///         var data = new DemoDTO
   ///                       {
   ///                          ID = Guid.NewGuid(),
   ///                          Geburtstag = new DateTime(2009, 7, 5),
   ///                          Nachname = "Demonachname",
   ///                          Vorname = "Demovorname"
   ///                       };
   ///         try
   ///         {
   ///            compressor.Save(data);
   ///            Console.WriteLine("File has successfully been saved." + Environment.NewLine);
   ///         }
   ///         catch(Exception problem)
   ///         {
   ///            Console.WriteLine(problem);
   ///         }
   ///         finally
   ///         {
   ///            data = null;
   ///         }
   ///      }
   ///
   ///      #region DemoHelper
   ///
   ///      /// <summary>
   ///      /// Holt den Pfad zum aktuellen Projekt-Ordner.
   ///      /// Dieses Property bitte nicht im Produktivcode benutzen.
   ///      /// </summary>
   ///      /// <returns>der Pfad zum aktuellen Projekt-Ordner.</returns>
   ///      private static string GetProjectPath(EnvironmentMode mode)
   ///      {
   ///         // Ergebnis: Debug- oder Release-Ordner im Projektordner.
   ///         string projectPath = Environment.CurrentDirectory;
   ///         // Mit jedem Durchlauf geht es im Verzeichnisbaum eine Stufe höher.
   ///         for(int i = 0; i < (int)mode; i++)
   ///         {
   ///            projectPath = Path.GetDirectoryName(projectPath);
   ///         }
   ///         return projectPath;
   ///      }
   ///
   ///      /// <summary>
   ///      /// Je nach Umgebung variiert die Anzahl der Stufen,
   ///      /// die in der Ordnerstruktur nach oben geklettert werden muß.
   ///      /// </summary>
   ///      private enum EnvironmentMode
   ///      {
   ///         /// <summary>
   ///         /// Klettert in der Ordnerstruktur 2 Stufen nach oben.
   ///         /// </summary>
   ///         Regular = 2,
   ///
   ///         /// <summary>
   ///         /// Klettert in der Ordnerstruktur 3 Stufen nach oben.
   ///         /// </summary>
   ///         UnitTests = 3
   ///      }
   ///
   ///      #endregion
   ///   }
   ///}
   ///
   /// ]]>
   /// </code>
   /// </example>
   public class CompressedBinaryFileIO
   {
      /// <summary>
      /// Initialisiert eine neue Instanz der <see cref="CompressedBinaryFileIO"/> Klasse.
      /// </summary>
      /// <param name="path">Der Dateipfad,
      ///  in dem die Datei gespeichert oder geladen werden soll
      /// (kein \ am Ende angeben).</param>
      /// <param name="filename">Dateiname ohne Extension</param>
      /// <param name="extension">Die Datei-Extension ohne vorangestellten Punkt.</param>
      public CompressedBinaryFileIO(string path, string filename, string extension)
      {
         Contract.Requires(!string.IsNullOrEmpty(path));
         Contract.Requires(!string.IsNullOrEmpty(filename));
         Contract.Requires(!string.IsNullOrEmpty(extension));
         Path = path;
         Filename = filename;
         Extension = extension;
         fullFilename = Path + @"\" + Filename + "." + Extension;
      }

      private static readonly Object syncLock = new Object();
      private readonly string fullFilename;

      /// <summary>
      /// Gibt den Pfad zurück, der im Konstruktor angegeben wurde.
      /// </summary>
      /// <value>The path.</value>
      public string Path { get; private set; }

      /// <summary>
      /// Gibt den Dateinamen zurück, der im Konstruktor angegeben wurde.
      /// </summary>
      /// <value>The filename.</value>
      public string Filename { get; private set; }

      /// <summary>
      /// Gibt die Datei-Extension zurück, der im Konstruktor angegeben wurde.
      /// </summary>
      /// <value>The extension.</value>
      public string Extension { get; private set; }

      /// <summary>
      /// Lädt eine komprimierte Datei, die im Konstruktor definiert wurde.
      /// Diese Methode ist threadsicher.
      /// </summary>
      /// <exception cref="Exception">Wirft Exceptions.</exception>
      public object Load()
      {
         lock(syncLock)
         {
            var filePermissions = new FileIOPermission(
               FileIOPermissionAccess.Read, fullFilename);
            filePermissions.Assert();

            var decompressedStream = new GZipStream(
               File.OpenRead(fullFilename), CompressionMode.Decompress);
            var formatter = new BinaryFormatter();
            object data = formatter.Deserialize(decompressedStream);
            decompressedStream.Close();
            decompressedStream.Dispose();
            formatter = null;
            return data;
         }
      }


      /// <summary>
      /// Speichert eine komprimierte Datei, die im Konstruktor definiert wurde.
      /// Im Falle daß die übergebenen Daten null, bricht die Methode ab.
      /// Diese Methode ist threadsicher.
      /// </summary>
      /// <returns>true wenn die Daten erfolgreich gespeichert wurden, anderenfalls false.</returns>
      /// <exception cref="Exception">Wirft Exceptions.</exception>
      public bool Save(object data)
      {
         lock(syncLock)
         {
            if(data == null)
               return false;
            var filePermissions = new FileIOPermission(
               FileIOPermissionAccess.Write, fullFilename);
            filePermissions.Assert();

            var compressedStream = new GZipStream(
               File.Create(fullFilename), CompressionMode.Compress);
            var formatter = new BinaryFormatter();
            formatter.Serialize(compressedStream, data);
            compressedStream.Close();
            compressedStream.Dispose();
            formatter = null;
            return true;
         }
      }
   }
}

1 Kommentare zum Snippet

Rainer Hilmer schrieb am 8/18/2009:
P.S.: Die Contracts-Klasse stammt aus dem Microsoft CodeContracts Framework.
http://research.microsoft.com/en-us/projects/contracts/
Wer es nicht instaliert hat, kann diese Zeilen durch entsprechende If-Abfragen ersetzen.
 

Logge dich ein, um hier zu kommentieren!