WP7独立存储之IsolatedStorageFile之图片的存储和读取
wp7的独立存储要用到 IsolatedStorageFile类:获取应用的独立存储区域,可以在该区域里创建、删除目录和文件,可以打开文件(返回文件的流),同时也要用到IsolatedStorageFileStream类:获取独立存储区域的文件的流。
打一个不大恰当的比喻:
IsolatedStorageFIle 相当于一个封闭的大仓库,里面放着很多箱子(相当于目录),箱子可能放着各种货物(相当于各种文件,如txt、jpg等)或者是更小的箱子(目录),
IsolatedStorageFileStream 相当于是仓库的门口,货物的运进运出只能通过从门口出入。
读取不同的文件还要用到不同的流,如文本文件用到 StreamReader 和 StreamWriter ,jpg文件用到 WriteableBitmap类。
Demo项目的界面就一个image控件和两个button控件,一个button的click事件是从图库里读取一张图片到独立存储区,另一个button的click事件是把独立存储区的指定照片读取出来显示到mage控件上。
不废话,直接上代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Net; 5 using System.Windows; 6 using System.Windows.Controls; 7 using System.Windows.Documents; 8 using System.Windows.Input; 9 using System.Windows.Media; 10 using System.Windows.Media.Animation; 11 using System.Windows.Shapes; 12 using Microsoft.Phone.Controls; 13 using System.IO.IsolatedStorage; 14 using Microsoft.Phone.Tasks; 15 using System.IO; 16 using System.Windows.Media.Imaging; 17 using System.Windows.Resources; 18 19 namespace myIsoFile 20 { 21 public partial class MainPage : PhoneApplicationPage 22 { 23 IsolatedStorageFile isoFile; 24 IsolatedStorageFileStream isoFileStream; 25 // 构造函数 26 public MainPage() 27 { 28 InitializeComponent(); 29 this.buttonReadFile.Click += new RoutedEventHandler(buttonReadFile_Click); 30 this.buttonWriter.Click += new RoutedEventHandler(buttonWriter_Click); 31 32 isoFile = IsolatedStorageFile.GetUserStoreForApplication(); 33 34 //创建目录 35 if (!isoFile.DirectoryExists("picture/myPhoto")) 36 { 37 isoFile.CreateDirectory("picture/myPhoto"); 38 } 39 40 //创建文件。如果创建的文件位于不存在的目录,则同时创建相应目录 41 if (!isoFile.FileExists("picture\\myPhoto\\123.jpg")) 42 { 43 // isoFile.DeleteFile("picture\\myPhoto\\123.jpg"); 44 isoFile.CreateFile("picture\\myPhoto\\123.jpg"); 45 } 46 //else 47 //{ 48 // isoFile.DeleteFile("picture\\myPhoto\\123.jpg"); 49 // isoFile.CreateFile("picture\\myPhoto\\123.jpg"); 50 //} 51 52 // isoFile.OpenFile("picture\\myPhoto\\123.jpg", FileMode.Open, FileAccess.Write, FileShare.Write); 53 54 } 55 56 //打开图片选择器 57 void buttonWriter_Click(object sender, RoutedEventArgs e) 58 { 59 if (isoFile.FileExists("picture\\myPhoto\\123.jpg")) 60 { 61 var myPhoto = new PhotoChooserTask(); 62 myPhoto.Completed += new EventHandler<PhotoResult>(myPhoto_Completed); 63 myPhoto.Show(); 64 } 65 } 66 67 //选择完图片之后保存到独立存储区 68 void myPhoto_Completed(object sender, PhotoResult e) 69 { 70 if (e.TaskResult == TaskResult.OK && e.Error == null) 71 { 72 using (isoFileStream = isoFile.OpenFile("picture\\myPhoto\\123.jpg", FileMode.Open, FileAccess.Write, FileShare.Write)) 73 { 74 75 //如果是一张已知路径的图片,可以如下获取它的流 76 // Uri uri = new Uri(photoPath, UriKind.Relative); 77 // StreamResourceInfo sri = Application.GetResourceStream(uri); 78 // sri.stream 表示图片的流 79 80 81 //用所选图片的资源的流创建 BitmapImage 82 BitmapImage bitmap = new BitmapImage(); 83 84 //把PhotoChooserTask返回的图片的流直接赋给BitmapImage所谓Source 85 bitmap.SetSource(e.ChosenPhoto); 86 87 //提供一个可写入并可更新的 BitmapSource。 88 WriteableBitmap wb = new WriteableBitmap(bitmap); 89 90 //把wb所表示的图片写到isoFileStream指向的文件,在这里是123.jpg 91 wb.SaveJpeg(isoFileStream, wb.PixelWidth, wb.PixelHeight, 0, 85); 92 93 // BitmapImage.SaveJpeg() 其实就是下面这个方法 94 // Extensions.SaveJpeg(wb, isoFileStream, wb.PixelWidth, wb.PixelHeight, 0, 85); 95 } 96 } 97 } 98 99 //从独立存储空间读取图片 100 void buttonReadFile_Click(object sender, RoutedEventArgs e) 101 { 102 if (isoFile.FileExists("picture\\myPhoto\\123.jpg")) 103 { 104 using (isoFileStream = isoFile.OpenFile("picture\\myPhoto\\123.jpg", FileMode.Open, FileAccess.Read)) 105 { 106 BitmapImage background = new BitmapImage(); 107 background.SetSource(isoFileStream); 108 this.image1.Source = background; 109 } 110 111 } 112 } 113 114 } 115 }
不过在这里碰到了一个问题,就是在独立存储区的目录下创建文件的问题,如下打开文件 123.jpg就没问题
1 //创建目录 2 if (!isoFile.DirectoryExists("picture/myPhoto")) 3 { 4 isoFile.CreateDirectory("picture/myPhoto"); 5 } 6 7 //创建文件。如果创建的文件位于不存在的目录,则同时创建相应目录 8 if (!isoFile.FileExists("picture\\myPhoto\\123.jpg")) 9 { 10 // isoFile.DeleteFile("picture\\myPhoto\\123.jpg"); 11 isoFile.CreateFile("picture\\myPhoto\\123.jpg"); 12 } 13 //else 14 //{ 15 // isoFile.DeleteFile("picture\\myPhoto\\123.jpg"); 16 // isoFile.CreateFile("picture\\myPhoto\\123.jpg"); 17 //} 18 19 isoFile.OpenFile("picture\\myPhoto\\123.jpg", FileMode.Open, FileAccess.Write, FileShare.Write);
但如下打开文件 jpg 在运行时就提示出错:
1 //创建目录 2 if (!isoFile.DirectoryExists("picture/myPhoto")) 3 { 4 isoFile.CreateDirectory("picture/myPhoto"); 5 } 6 7 //创建文件。如果创建的文件位于不存在的目录,则同时创建相应目录 8 if (isoFile.FileExists("picture\\myPhoto\\123.jpg")) 9 { 10 isoFile.DeleteFile("picture\\myPhoto\\123.jpg"); 11
12 } 13
14 15 16 isoFile.CreateFile("picture\\myPhoto\\123.jpg"); 17 18 19 isoFile.OpenFile("picture\\myPhoto\\123.jpg", FileMode.Open, FileAccess.Write, FileShare.Write);
也就是说,先删除再创建在运行时打开就出错,不知何解,求答案!
终于,思考了一天,找到答案了。
第二种情况,调用CreateFile方法来创建文件,该方法会返回该文件的流!就相当于文件是处于被打开的状态!那么如果下次再打开该文件(openFile)那么就会造成重复打开,所以出错!可以改成如下代码: var fileStream = isoFile.CreateFile("picture\\myPhoto\\123.jpg"); fileStream.Close(); 这样子下次再打开就不会出错了。
第一种情况也是CreateFile,为什么就没错呢?其实第一种情况在第一次运行的时候在openFile时也是出错的,那你肯定会停止运行,看一下代码,觉得没什么错误,然后再次运行。关键就在这里,因为是在独立存储区里创建文件,在第一次运行时123.jpg文件就已经被创建好了,那么你第二次以后的运行就不会进入到if条件里,就不会重新创建,也就不会打开123.jpg,所以第二次以后再运行就不会出错。