Eelmises postituses mainisin, et eile tegelesin programmiga, mis kustutaks kataloogist kõik pildid, mida ei ole võimalik avada. Miks? Ma nimelt taastasin terve hunniku faile (nende hulgas ka pilte) kettalt, kuhu oli värskelt installeeritud op. süsteem ja seda kasutama hakatud ning seejärel avastati, et failid k.a. pildid jäid kopeerimata ning olid nüüd kaotsi läinud. Kõik failid, millele ei oldud veel jõudnud kirjutada, oli võimalik taastada. Aga igaks juhuks proovisin taastada ka neid faile, millel oli taastamisprogrammil punane või orants ikoon ees (suure tõenäosusega ei õnnestu taastada). Seega taastati ka faile, mis tegelikult polnud avatavad. Veidi üle 12000 pildi taastati ja mitte ei tahtnud käsitsi läbi käia pilte ja kustutada ükshaaval need, mis pole avatavad.
Tagasi programmi juurde.
Alguses proovisin kasutada Image klassi, aga kahjuks lockib see failid mõneks ajaks. Seega on kustutamine keerukas (isegi pärast Dispose –i oli fail veel kinni ning kohene kustutamine polnud võimalik). Otsisin alternatiivi WPF –st. WPF –s on olemas niisugune klass nagu BitmapImage. Selleks peate refereerima:
- WindowsBase.dll
- PresentationCore.dll
Peale mõningast uurimist ja testimist jõudsin järgneva töötava lahenduseni:
1: var files = Directory.GetFiles(@"E:\Data\BUps\Test\", "*.jpg");
2:
3: foreach (var file in files)
4: {
5: BitmapImage image = new BitmapImage();
6: try
7: {
8: image = new BitmapImage();
9: image.BeginInit();
10: image.StreamSource = new FileStream(file, FileMode.Open, FileAccess.Read);
11: image.CacheOption = BitmapCacheOption.None;
12: image.EndInit();
13: image.StreamSource.Dispose();
14: }
15: catch (FileFormatException exc)
16: {
17: image.StreamSource.Dispose();
18: File.Delete(file);
19: }
20: catch (NotSupportedException exc)
21: {
22: image.StreamSource.Dispose();
23: File.Delete(file);
24: }
25: }
Kui fail polnud avatav, siis sain ma kahte tüüpi vigasid – faili formaat polnud toetatud või siis ei saadud aru, et tegu on pildi failiga üldse. Nendel puhkudel kustutasin.
Properteid muudan ma BeginInit ja EndInit vahel, kuna muul juhul nende muutmine ignoreeritakse. BitmapImage implementeerib niisugust liidest nagu ISupportInitialize.
Niimoodi õnnestus mul pilti laadida ilma, et fail oleks lukustatud. Ja peale Dispose –i sain seda edukalt teha.
Täiendus: Kui nüüd aus olla, eile öösel mul see Image klassiga ja Dispose –imisega ei toiminud. Fail oli lukus. Hetkel aga toimis. Seega kui Image ilusti Dispose –da, siis fail pole lukus ja kustutamine on võimalik koheselt.
Igatahes, huvitav oli kasutada WPF –i klassi ja väga lihtne kood tuli.
Image klassiga näeks lahendus välja järgmine:
1: var files =
2: Directory.GetFiles(
3: @"E:\Data\BUps\Kristel\Test\",
4: "*.jpg"
5: );
6:
7: foreach (var file in files)
8: {
9: try
10: {
11: using (var image = Image.FromFile(file))
12: {
13: //Teen midagi pildiga
14: }
15: }
16: catch (Exception exc)
17: {
18: File.Delete(file);
19: }
20: }
Ma tegin lisaks ka pisikese jõudlustesti Image klassi ja WPF klassi vahel.
Need koodid käies läbi 341 pilti kogusuurusega 80MB võttis:
- Image klassi puhul aega: 12661 ms (12 sekundit)
- WPF klassi puhul aega: 966 ms (alla sekundi)
Huvitav info. Edu.