GlobalCache.cs (7574B)
1 using System; 2 using System.Collections.Generic; 3 using System.IO; 4 using System.Security.Cryptography; 5 6 namespace LanTool.Classes 7 { 8 /// <summary> 9 /// Beinhaltet die globalen CacheListe des LanTools 10 /// </summary> 11 public class GlobalCache : IDisposable 12 { 13 #region Konstanten für die Caches 14 15 private const string cHashKeyCacheFile = "LanTool.cache"; 16 private const string cHashKeyExcludeFile = "LanTool.exclude"; 17 private const string cHashKeyIgnoreFile = "LanTool.ignore"; 18 19 #endregion 20 21 #region Properties 22 23 /// <summary> 24 /// Cache mit allen Hash-Werten von bekannten Dateien 25 /// </summary> 26 public SortedDictionary<string, string> HashCache { get; private set; } 27 /// <summary> 28 /// Cache mit allen Hash-Werten, die gesperrt sind 29 /// </summary> 30 public List<String> ExcludeCache { get; private set; } 31 /// <summary> 32 /// Cache mit allen Hash-Werten, bei denen Dubletten ignoriert werden 33 /// </summary> 34 public List<String> IgnoreCache { get; private set; } 35 36 #endregion 37 38 #region Fields mit den Caches 39 40 private long hashOldInCache = 0; 41 private long hashNewInCache = 0; 42 private string _basePath; 43 44 private MD5 md5; 45 46 #endregion 47 48 /// <summary> 49 /// Konstruktor für den globalen Cache 50 /// Legt die Cachelisten an und füllt diese von den Platten 51 /// </summary> 52 /// <param name="basePath">Standard-Pfad</param> 53 public GlobalCache(string basePath) 54 { 55 this._basePath = basePath; 56 57 this.HashCache = new SortedDictionary<string, string>(); 58 this.ExcludeCache = new List<string>(); 59 this.IgnoreCache = new List<string>(); 60 61 md5 = MD5.Create(); 62 63 // Caches einlesen 64 LoadCacheFromDisk(); 65 LoadExcludeListFromDisk(); 66 LoadIgnoreListFromDisk(); 67 } 68 69 /// <summary> 70 /// Speichert alle Liste auf Festplatte 71 /// </summary> 72 public void Dispose() 73 { 74 Dispose(true); 75 GC.SuppressFinalize(this); 76 } 77 78 /// <summary> 79 /// Speichert alle Liste auf Festplatte 80 /// </summary> 81 /// <param name="yes"></param> 82 protected virtual void Dispose(Boolean yes) 83 { 84 if (yes) 85 { 86 } 87 88 SaveCacheToDisk(); 89 SaveExcludeListToDisk(); 90 SaveIgnoreListToDisk(); 91 } 92 93 #region Behandlung der globalen Cache-Liste 94 95 /// <summary> 96 /// MD5-Cache von der Platte laden 97 /// </summary> 98 private void LoadCacheFromDisk() 99 { 100 HashCache.Clear(); 101 if (File.Exists(_basePath + cHashKeyCacheFile)) 102 { 103 using (StreamReader cacheReader = File.OpenText(_basePath + cHashKeyCacheFile)) 104 { 105 string s; 106 while ((s = cacheReader.ReadLine()) != null) 107 { 108 if ( s.Length > 44 ) 109 { 110 HashCache[ s.Substring( 44 ) ] = s.Substring( 0, 43 ); 111 } 112 } 113 } 114 Program.MainWindow.Log(cHashKeyCacheFile + " wurde mit " + HashCache.Keys.Count.ToString() + " Einträgen geladen."); 115 } 116 else 117 { 118 Program.MainWindow.LogWarning(cHashKeyCacheFile + " nicht vorhanden."); 119 } 120 } 121 122 /// <summary> 123 /// MD5-Cache auf Platte speichern 124 /// </summary> 125 public void SaveCacheToDisk() 126 { 127 try 128 { 129 using (StreamWriter sw = File.CreateText(_basePath + cHashKeyCacheFile)) 130 { 131 foreach (KeyValuePair<string, string> di in HashCache) 132 { 133 sw.WriteLine(di.Value + "/" + di.Key); 134 } 135 } 136 Program.MainWindow.Log(cHashKeyCacheFile + " wurde mit " + HashCache.Keys.Count.ToString() + " Einträgen gespeichert (" + hashNewInCache.ToString() + " neue Einträge, " + hashOldInCache.ToString() + " Treffer)"); 137 } 138 catch (Exception e) 139 { 140 Program.MainWindow.LogError(cHashKeyCacheFile + " konnte nicht gespeichert werden: " + e.Message); 141 } 142 } 143 144 /// <summary> 145 /// Löschen des Hash-Caches 146 /// </summary> 147 public void Clear() 148 { 149 HashCache.Clear(); 150 151 hashNewInCache = 0; 152 hashOldInCache = 0; 153 154 SaveCacheToDisk(); 155 } 156 157 /// <summary> 158 /// Aus Datei einen Hashkey erzeugen oder aus dem Cache entnehmen 159 /// </summary> 160 /// <param name="file">Datei</param> 161 /// <returns>Hash-Key</returns> 162 public string GetHashCodeFromFileHeader(string file) 163 { 164 if (String.IsNullOrEmpty(file)) 165 { 166 return String.Empty; 167 } 168 169 Int32 md5HashSize = Program.MainWindow.m_Config.MD5FileSize; 170 171 // Nachsehen, ob der Länge / Dateipfad gecached sind 172 if (HashCache.ContainsKey(md5HashSize + " " + file)) 173 { 174 hashOldInCache++; 175 return HashCache[md5HashSize + " " + file]; 176 } 177 178 // wenn die Datei nicht existiert, keinen Fehler melden 179 // sondern leeren String, Datei wird später als Lesefehler markiert 180 if (!File.Exists(file)) 181 { 182 return String.Empty; 183 } 184 185 try 186 { 187 // Teil 1 des Hashcodes ist die Dateigröße 188 FileInfo fi = new FileInfo(file); 189 string hash = fi.Length.ToString("X10"); 190 // Teil 2 des Hascode ist das md5 über x Bytes. Bei Netzwerkzugriff 191 // ist das etwas zu viel die ganzen Dateien zu lesen 192 byte[] buffer = new byte[md5HashSize]; 193 using (FileStream fs = fi.OpenRead()) 194 { 195 int gelesen = fs.Read(buffer, 0, md5HashSize); 196 197 // Wenn die Datei leer ist, den Dateinamen nehmen 198 if (gelesen == 0) 199 { 200 for (int i = 0; i < file.Length; i++) 201 buffer[i] = (byte)file[i]; 202 } 203 } 204 205 byte[] mdhash = md5.ComputeHash(buffer); 206 hash = "/" + hash; 207 foreach (byte b in mdhash) 208 { 209 hash = b.ToString("X2") + hash; 210 } 211 212 // Im Cache ablegen für weitere Verwendung 213 HashCache[md5HashSize + " " + file] = hash; 214 hashNewInCache++; 215 return hash; 216 } 217 catch 218 { 219 return String.Empty; 220 } 221 } 222 223 #endregion 224 225 /// <summary> 226 /// Exclude-Liste von Platte laden 227 /// </summary> 228 private void LoadExcludeListFromDisk() 229 { 230 ExcludeCache.Clear(); 231 if (File.Exists(_basePath + cHashKeyExcludeFile)) 232 { 233 // Alle Zeilen der Datei in den Cache einlesen 234 ExcludeCache.AddRange(File.ReadAllLines(_basePath + cHashKeyExcludeFile)); 235 236 Program.MainWindow.Log(cHashKeyExcludeFile + " wurde mit " + ExcludeCache.Count.ToString() + " Einträgen geladen"); 237 } 238 else 239 { 240 Program.MainWindow.LogWarning(cHashKeyExcludeFile + " nicht vorhanden."); 241 } 242 } 243 244 /// <summary> 245 /// Exclude-Liste auf Platte speichern 246 /// </summary> 247 public void SaveExcludeListToDisk() 248 { 249 try 250 { 251 // Alle Zeilen des Exclude-Caches in die Datei schreiben 252 File.WriteAllLines(_basePath + cHashKeyExcludeFile, ExcludeCache.ToArray()); 253 254 Program.MainWindow.Log(cHashKeyExcludeFile + " wurde mit " + ExcludeCache.Count.ToString() + " Einträgen gespeichert"); 255 } 256 catch (Exception e) 257 { 258 Program.MainWindow.LogError(cHashKeyExcludeFile + "konnte nicht gespeichert werden: " + e.Message); 259 } 260 } 261 262 /// <summary> 263 /// Exclude-Liste von Platte laden 264 /// </summary> 265 private void LoadIgnoreListFromDisk() 266 { 267 IgnoreCache.Clear(); 268 if (File.Exists(_basePath + cHashKeyIgnoreFile)) 269 { 270 // Alle Zeilen in den IgnoreCache laden 271 IgnoreCache.AddRange(File.ReadAllLines(_basePath + cHashKeyIgnoreFile)); 272 273 Program.MainWindow.Log(cHashKeyIgnoreFile + " wurde mit " + IgnoreCache.Count.ToString() + " Einträgen geladen"); 274 } 275 else 276 { 277 Program.MainWindow.LogWarning(cHashKeyIgnoreFile + " nicht vorhanden."); 278 } 279 } 280 281 /// <summary> 282 /// Exclude-Liste auf Platte speichern 283 /// </summary> 284 public void SaveIgnoreListToDisk() 285 { 286 try 287 { 288 File.WriteAllLines(_basePath + cHashKeyIgnoreFile, IgnoreCache.ToArray()); 289 Program.MainWindow.Log(cHashKeyIgnoreFile + " wurde mit " + IgnoreCache.Count.ToString() + " Einträgen gespeichert"); 290 } 291 catch (Exception e) 292 { 293 Program.MainWindow.LogError(cHashKeyIgnoreFile + "konnte nicht gespeichert werden: " + e.Message); 294 } 295 } 296 } 297 }