Archiwista [cz. 10 – Kopie zapasowe cd.]
W tym tygodniu pracowałem głównie nad tworzeniem kopii. Ostatnim razem zabrakło czasu na stworzenie metody, która zwalnia miejsce na dysku w przypadku jego przepełnienia. Pozostawia ona również ostatnią kopię z każdego dnia dzięki czemu będziemy mieli jakąś historię do której możemy wrócić jeżeli będziemy mieli taką potrzebę.
Ustawienia
Usunięcie stworzonych kopii wiążę się z ich odnalezieniem na dysku twardym. W związku z tym potrzebna jest baza projektów, które użytkownik dodał. Z pomocą przychodzą ustawienia, w których będą przechowywane wszelkie informacje użytkownika. Stworzyłem dwie klasy. Settings przechowującą wszelkie informacje, które użytkownik może zmieniać. Drugą klasą jest Storage odpowiada ona za wczytywanie i zapisywanie ustawień. W celu łatwego odzwierciedlenia klasy w pliku wykorzystałem XmlSerializer, pozwala on w prosty sposób zamienić każdą klasę na strukturę XML. Działa to również w drugą stronę. XmlSerializer umożliwia odczytanie tak zapisanej struktury z pliku i tworzy gotowy obiekt, z którego można korzystać.
Procedura zapisu jest prosta wystarczy stworzyć obiekt Serializera podając odpowiedni typ danych. Aby utworzyć plik wystarczy wywołać metodę Serialize podając otwarty strumień oraz obiekt do zapisania.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public static void Save() { if (Settings == null) return; XmlSerializer xs = new XmlSerializer(typeof(UserSettings)); using (TextWriter tw = new StreamWriter(SettingsPath)) { xs.Serialize(tw, Settings); } } |
Odczyt danych wygląda podobnie nie mniej jednak napotkałem tutaj problem. Podczas odczytu cała procedura odbywa się prawidłowo i dane w zwróconym obiekcie są prawidłowe mimo to rzucany jest wyjątek o tym że plik już jest odczytywany przez jakiś proces. Postaram się rozwiązać ten problem następnym razem.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public static void Load() { XmlSerializer xs = new XmlSerializer(typeof(UserSettings)); try { using (var sr = new StreamReader(SettingsPath)) { Settings = xs.Deserialize(sr) as UserSettings; } } catch (InvalidOperationException e) { // Some error with settings file, create Default one. Settings = new UserSettings(); Save(); } catch (IOException e) { //TODO: find out why this error occurs, that something is reading file already, // even if it gets good data. Console.WriteLine(e.Message); } } |
Czyszczenie
Wracając do głównego celu tego wpisu czyli procesu oczyszczania dysku z utworzonych kopii. Stworzyłem metodę ClearDriveSpace pobiera ona z ustawień użytkownika wszystkie projekty, następnie przeszukuje je w poszukiwaniu kopii zapasowych. Cały proces okazał się trochę skomplikowany przez zastosowaną strukturę katalogów nie mniej jednak metoda działa. Poszukuje ona kopie i usuwa wszystkie oprócz ostatniej z danego dnia. Patrząc teraz na ten kod widzę tutaj miejsce na poprawę, na pewno wrócę do tej metody jeszcze raz, aby poprawić jej czytelność.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
public static ClearResult ClearDriveSpace() { var result = ClearResult.Fail; // -Get into projcet copies foreach (var project in Storage.Settings.Projects) { var Projects = GetAllDirectories(project.ArchivePath); foreach(var projectPath in Projects) { var Days = GetAllDirectories(projectPath); foreach(var day in Days) { var ProjectArchiveDirectories = GetAllDirectories(day); foreach(var archiveDirectory in ProjectArchiveDirectories) { var ProjectCopies = GetAllFiles(archiveDirectory); // If there is only 1 copie leave it if (ProjectCopies.Length > 1) { // Else clear all but lastest copie assuming that they are sorted for (int i = 0; i < ProjectCopies.Length - 1; i++) { if (File.Exists(ProjectCopies[i])) { File.Delete(ProjectCopies[i]); result = ClearResult.Success; } } } } } } } if (result == ClearResult.Fail) { MessageBox.Show("Hard Drive is full.\nMake more space!", "No space left!", MessageBoxType.Ok); } return result; } |
Kończąc
W tym tygodniu zrobiłem duży krok ku końcowi tworząc mechanizm ustawień. Poprawiłem kilka drobnych błędów oraz znalazłem kilka nowych, nad których rozwiązaniem jeszcze będę musiał się zastanowić. Pierwszym z błędów, jaki znalazłem jest brak przewijania tekstu do końca w polu kodu źródłowego. Wstępna diagnoza pokazała, że dzieje się tak poprzez zastosowanie stylu weryfikującego poprawność wypełnienia pola. Kolejnym błędem, jaki znalazłem jest przytrzymanie skrótu klawiszowego zakleszcza program. Będę musiał tutaj zastosować jakiś mechanizm opóźniający kolejne wywoływania tworzenia kopii bądź kolejkę, o której wspominałem w jednym z wcześniejszych wpisów. Ostatni rzucający się w oczy jest błąd występujący podczas wczytywania ustawień. Proces wczytania następuje prawidłowo po czym rzucany jest wyjątek o tym że plik jest odczytywany przez inny proces. Nie znalazłem jeszcze przyczyny będę musiał to zdiagnozować dokładniej. Aplikacja nabiera już kształtów niedługo będzie można z niej normalnie korzystać. Do jej skończenia pozostało jeszcze parę tygodni, ale jest już bliżej niż dalej.
[KodNaGit]