Storage Class

ByteStorage

In meinem momentanen privaten Bilderverwaltungsprojekt habe ich eine effiziente Möglichkeit gesucht verkleinerte Vorschaubilder zu speichern. Die Angehängte kleine Klasse hat mir dabei geholfen.
Es werden 2 Dateien angelegt, eine Datei die, die Daten hält (*.cache) und eine die diese indiziert hat und den Zugriff beschleunigt (*.cacheindex).

Das ganze läuft Threadsafe ab und kann somit von mehreren Threads gleichzeitig verwendet werden ohne, dass die Zugriffe sich gegenseitig stören.

[codesyntax lang="csharp"]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary; 

namespace mCollection
{
    public class ByteStorage : IDisposable
    {
        /// <summary>
        /// The Filestream which is beeing used
        /// </summary>
        private FileStream m_Stream;
        /// <summary>
        /// Contains string as key and a Tuple <long as length of data, long as offset>
        /// </summary>
        private Dictionary<string, Tuple<long, long >> Indices;

        private string PathToCachingFile;
        private string PathToIndexFile;

        /// <summary>
        /// Ctor
        /// </summary>
        /// <param name="TargetDirectory">Directory which contains the index&caching File</param>
        /// <param name="Filename">Filename (*.cacheindex and *.cache will be generated/opened)</param>
        public ByteStorage(string TargetDirectory, string Filename)
        {
            PathToCachingFile = Path.Combine(TargetDirectory, Filename + ".cache");
            PathToIndexFile = Path.Combine(TargetDirectory, Filename + ".cacheindex");

            m_Stream = new FileStream(PathToCachingFile, FileMode.OpenOrCreate);

            if (!File.Exists(PathToIndexFile))
            {
                Indices = new Dictionary<string, Tuple<long, long>>();
            }
            else
            {
                BinaryFormatter binFormatter = new BinaryFormatter();
                using (FileStream fs = new FileStream(PathToIndexFile, FileMode.Open))
                {
                    Indices = (Dictionary<string, Tuple<long, long>>)binFormatter.Deserialize(fs);
                }
            }
        }

        ~ByteStorage()
        {
            Dispose();
        }

        public byte[] GetData(string Key)
        {
            try
            {
                Tuple<long, long> tuple;
                if(Indices.TryGetValue(Key , out tuple))
                {
                    byte[] buffer = new byte[tuple.Item1];
                    lock (this)
                    {
                        long tmp = m_Stream.Position;
                        m_Stream.Position = tuple.Item2;
                        m_Stream.Read(buffer, 0, buffer.Length);
                        m_Stream.Position = tmp;
                    }
                    return buffer;
                }
                return null;
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// Method for adding some byte[] data to the cachingfile
        /// </summary>
        /// <param name="Key"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public bool AddData(string Key, byte[] data)
        {
            try
            {
                byte[] buffer = new byte[data.Length + sizeof(int)];
                Array.Copy(data, buffer, data.Length);
                byte[] length = System.BitConverter.GetBytes(data.Length);
                Array.Copy(length, 0, buffer, data.Length, length.Length);

                long offset = 0;
                lock (this)
                {
                    long tmp = m_Stream.Position;
                    offset = m_Stream.Length;
                    m_Stream.Position = offset;
                    m_Stream.Write(buffer, 0, buffer.Length);
                    m_Stream.Position = tmp;
                    Indices.Add(Key, new Tuple<long, long>(data.Length, offset));
                    SafeIndices();
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

        private void SafeIndices()
        {
            if (Indices == null)
                return;

            BinaryFormatter binFormatter = new BinaryFormatter();
            lock (this)
            {
                using (FileStream fs = new FileStream(PathToIndexFile, FileMode.OpenOrCreate))
                {
                    binFormatter.Serialize(fs, Indices);
                }
            }
        }

        public void Dispose()
        {
            SafeIndices();
            if (m_Stream == null)
                return;
            m_Stream.Close();
            m_Stream.Dispose();
            m_Stream = null;
        }
    }
}

[/codesyntax]