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]




