独立存储
独立存储机制是从Silverlight中提取出来的技术,最初的目的是为Silverlight应用程序提供一个客户端安全的存储,在代码与保存的数据之间定义了标准化的关联机制,它是一个与Cookie机制类似的信任机制,可以为数据提供很好的隔离性和安全性。而实际上,在Silverlight中,所有的I/O操作的处理都被视为独立存储,不使用操作系统的文件系统。
独立存储的API提供了一个虚拟的文件操作系统(IsolatedStorageFile),提供对存储的程序和应用程序文件的基本管理,每一个IsolatedStorageFile的实例表示位于文件系统中的一个单独存储区。API还提供了数据流(IsolatedStorageFileStream)的操作用于存储区的文件。使用者还可以使用IsolatedStorageScope枚举值来创建并选择具有适当隔离类 型的存储区。
在Windows Phone中继续使用来自Silverlight的独立存储概念。区别只是在Windows Phone 中没有文件大小的限制。
在Windows Phone中,有关独立存储的操作主要使用的是位于System.IO.IsolatedStorage命名空间下的类:
- IsolatedStorageFile(表示包含文件和目录的独立存储区)
- IsolatedStorageFileStream(流操作)
- IsolatedStorageSettings(提供一个在独立存储中存储数据的键值对)
- IsolatedStorageException(独立存储中的操作失败时引发的异常)
IsolatedStorageFile
IsolatedStorageFile表示包含文件和目录的独立存储区,它用来获得实例的方法不是使用构造函数,而是:
IsolatedStorageFile myIsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication();
我们通过使用它的一些属性和方法来实现独立存储。
常用属性:
- AvailableFreeSpace 获取一个值,该值表示独立存储的可用空间量。
- IsEnabled 获取一个值,该值指示是否启用了独立存储。
- Quota 获取一个值,该值表示独立存储的最大可用空间量。
- UsedSize 获取一个值,该值表示用于独立存储的空间量。
常用方法:
- CopyFile,将现有文件复制到新文件,它有一个重载函数用来判断是不是覆盖现有文件,即CopyFile(String, String, Boolean)。
- CreateDirectory 在独立存储范围中创建目录。
- CreateFile 在独立存储区中创建文件。
- DeleteDirectory 删除独立存储范围中的目录。
- DeleteFile 删除独立存储区中的文件。
- DirectoryExists 确定指定的路径是否指的是独立存储区中的现有目录。
- Dispose 释放由 IsolatedStorageFile 使用的所有资源。
- FileExists 确定指定的路径是否指的是独立存储区中的现有文件。
- GetCreationTime 返回指定文件或目录的创建日期和时间。
- GetDirectoryNames 枚举独立存储区根处的目录。
- GetDirectoryNames(String) 枚举独立存储范围中与给定模式匹配的目录。
- GetFileNames 获取独立存储区根处的文件的名称。
- GetFileNames(String) 枚举独立存储范围中与给定模式匹配的文件。
- GetLastAccessTime 返回上次访问指定文件或目录的日期和时间。
- GetLastWriteTime 返回上次写入指定文件或目录的日期和时间。
- GetUserStoreForApplication 获取从虚拟主机域调用的应用程序所使用的用户范围的独立存储。
- GetUserStoreForSite 获取由虚拟主机域中的所有应用程序使用的某个用户范围的独立存储。
- IncreaseQuotaTo 使应用程序显式请求一个更大的配额大小,以字节为单位。
- MoveDirectory 将指定的目录及其内容移到新位置。
- MoveFile 将指定文件移到新位置,还可以允许您指定新文件名。
- OpenFile,打开文件,配合流的操作进行文件的读写,不同的重载方法实现不同打开方式,有OpenFile(String, FileMode)(在指定的模式中打开文件)、OpenFile(String, FileMode, FileAccess) (以指定的文件访问权限在指定的模式下打开文件)、OpenFile(String, FileMode, FileAccess, FileShare)(用读、写或读/写访问权限和指定的共享选项在指定的模式中打开文件)
- Remove 移除独立存储区范围及其所有内容。
IsolatedStorageFileStream
公开独立存储中的文件,使用流的方式来操作文件。获取实例的方法:
IsolatedStorageFileStream myFileStream=myIsolatedStorageFile.OpenFile("content.txt",FileMode.OpenOrCreate,FileAccess.Write);
它可以配合StreamWriter与StreamReader来实现读写。
常用属性:
- CanRead 已重写。获取一个布尔值,该值指示该文件是否可读。
- CanSeek 已重写。获取一个布尔值,该值指示查找操作是否受支持。
- CanTimeout 获取一个值,该值确定当前流是否可以超时。
- CanWrite 已重写。获取一个布尔值,该值指示是否可以写入文件。
- Length 已重写。获取 IsolatedStorageFileStream 对象的长度。
- Name 获取传递给构造函数的 FileStream 的名称。
- Position 已重写。获取当前 IsolatedStorageFileStream 对象的当前位置或将该位置设置为指定值。
- ReadTimeout 获取或设置一个值,该值确定流在超时前尝试读取多长时间。
- WriteTimeout 获取或设置一个值,该值确定流在超时前尝试写入多长时间。
常用方法:
- BeginRead 开始异步读。
- BeginWrite 开始异步写。
- Close 关闭当前流并释放与之关联的所有资源(如套接字和文件句柄)。 (从 Stream 继承。
- EndRead 结束挂起的异步读取请求。
- EndWrite 结束异步写入。
- Flush 用缓冲区的当前状态更新文件,然后清除缓冲区。
- Read 将字节从当前缓冲的 IsolatedStorageFileStream 对象复制到数组。
- ReadByte 从独立存储中的 IsolatedStorageFileStream 对象读取一个字节。
- Seek 将此 IsolatedStorageFileStream 对象的当前位置设置为指定值。
- SetLength 将此 IsolatedStorageFileStream 对象的长度设置为指定的 value。
- Write 使用从字节数组中读取的数据将字节块写入 IsolatedStorageFileStream 对象。
- WriteByte 将一个字节写入 IsolatedStorageFileStream 对象。
IsolatedStorageSettings
提供一个在独立存储中存储键/值对的 Dictionary(Of TKey, TValue)。它就是存储一个可供使用的数据的键值对,一般是比较少的数据,而使用IsolatedStorageFile来存储的是以文件的形式存储的数据,一般比较大。获取实例的方法:
private IsolatedStorageSettings myIsolatedStorageSettings = IsolatedStorageSettings.ApplicationSettings;
常用属性:
- ApplicationSettings 获取一个 IsolatedStorageSettings 实例,该实例包含应用程序的应用程序级 IsolatedStorageFile 的内容;如果不存在这样的实例,则创建一个新的 IsolatedStorageSettings 实例。
- Count 获取存储在字典中的键/值对的数目。
- Item 获取或设置与指定的键相关联的值。
- Keys 获取包含词典中的键的集合。
- SiteSettings 获取一个 IsolatedStorageSettings 实例,该实例包含应用程序的域级 IsolatedStorageFile 的内容;如果不存在这样的实例,则创建一个新的IsolatedStorageSettings 实例。
- Values 获取包含词典中的值的集合。
常用方法:
- Add 将键/值对的对应项添加到字典中。
- Clear 将 IsolatedStorageSettings 中存储的项的计数重置为零,并释放对集合中元素的所有引用。
- Contains 确定应用程序设置字典是否包含指定键。
- Remove 移除具有指定键的项。
- Save 保存写入到当前 IsolatedStorageSettings 对象的数据。
- TryGetValue(Of T) 获取指定键的值。
注意:一般的,在写IsolatedStorageFile等的实例的时候,由于单词IsolatedStorageFile 比较长,我们可以写作var使系统区识别,这也算一个小技巧了。如:
var myIsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication();
下面是一个简单地例子,我们使用一个简单地qq登录界面来说明问题,假设在用户使用qq登录功能的时候,因为一些事情而离开了登录界面,在不重启手机的情况下,当用户再次进入到qq登录界面的时候,自动显示出用户之前填写的用户名和密码(在这里不考虑用户是否有意愿去显示密码,而且使用TextBox)。而在登录界面中多写一个TextBox来记录用户输入的信息。
独立存储的具体实现:
- 登录账号及密码使用IsolatedStorageSetting来实现
- 信息记录使用IsolatedStorageFile来实现
特别的,在App.xaml.cs这个全局性的文件中定义方法SaveToFile来实现数据保存,定义方法ReadFromFile来实现数据读取,在每次关闭的时候调用SaveToFile函数在方法Application_Deactivated与Application_Closing方法中使用SaveToFile,在Application_Activated方法和Application_Launching方法中使用ReadFromFile。另外:
在App.xaml.cs中的这四个重要的方法(app可以理解为继承自Application类的子类):
Application_Launching,应用程序启动(例如,从“开始”菜单启动)时执行的代码,此代码在重新激活应用程序时不执行。
Application_Activated, 激活应用程序(置于前台)时执行的代码,此代码在首次启动应用程序时不执行。
Application_Deactivated,停用应用程序(发送到后台)时执行的代码,此代码在应用程序关闭时不执行。
Application_Closing,应用程序关闭(例如,用户点击“后退”)时执行的代码,此代码在停用应用程序时不执行。
具体过程:
1.在页面中添加三个TextBlock来进行标签性的说明,三个TextBox来使用户输入信息。布局如图:
代码:
<!--ContentPanel - 在此处放置其他内容--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <TextBlock Height="54" HorizontalAlignment="Left" Margin="30,55,0,0" Name="textBlock1" Text="姓名:" VerticalAlignment="Top" FontSize="32" Width="96" /> <TextBlock Height="54" HorizontalAlignment="Left" Margin="30,130,0,0" Name="textBlock2" Text="密码:" VerticalAlignment="Top" FontSize="32"/> <TextBlock Height="54" HorizontalAlignment="Left" Margin="30,277,0,0" Name="textBlock4" Text="信息:" VerticalAlignment="Top" FontSize="32"/> <TextBox Height="72" HorizontalAlignment="Left" Margin="115,37,0,0" Name="userName" Text="" VerticalAlignment="Top" Width="307" TextChanged="userName1_TextChanged"/> <TextBox Height="72" HorizontalAlignment="Left" Margin="115,112,0,0" Name="password" Text="" VerticalAlignment="Top" Width="307" TextChanged="password1_TextChanged"/> <TextBox HorizontalAlignment="Left" Margin="115,277,0,36" Name="myInfo" Text="" Width="307" TextWrapping="Wrap" TextChanged="myInfo_TextChanged"/> </Grid>
2.获取IsolatedStorageSetting的实例,并添加每个TextBox的TextChanged事件。
private IsolatedStorageSettings myIsolatedStorageSettings = IsolatedStorageSettings.ApplicationSettings;//获取IsolatedStorageSettings实例 private void userName1_TextChanged(object sender, TextChangedEventArgs e) { myIsolatedStorageSettings["userName"] = this.userName.Text.ToString(); } private void password1_TextChanged(object sender, TextChangedEventArgs e) { myIsolatedStorageSettings["password"] = this.password.Text.ToString(); }
3.添加页面的读取PhoneApplicationPage_Loaded事件。
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e) { string userName1 = ""; string password1 = ""; if (myIsolatedStorageSettings.Contains("userName")) { if (myIsolatedStorageSettings.TryGetValue<string>("userName", out userName1))//说明获取了userName1 { this.userName.Text=userName1; } } if (myIsolatedStorageSettings.Contains("password")) { if (myIsolatedStorageSettings.TryGetValue<string>("password", out password1))//说明获取了userName1 { this.password.Text = password1; } } }
4.在App.xaml.cs中添加两个方法,分别实现存储和读取。另外添加一个string,来存储共享数据。
public string Content { set; get; } public void SaveToFile() { using (IsolatedStorageFile myIsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication()) { if (!myIsolatedStorageFile.DirectoryExists("MyFolder"))//如果不存在文件夹“MyFolder” { myIsolatedStorageFile.CreateDirectory("MyFolder");//创建文件夹 } using(IsolatedStorageFileStream myFileStream=myIsolatedStorageFile.OpenFile("MyFolder\\content.txt",FileMode.OpenOrCreate,FileAccess.Write)) { using (StreamWriter myWriter = new StreamWriter(myFileStream)) { myWriter.WriteLine(Content); } } } } public void ReadFromFile() { using (IsolatedStorageFile myIsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication()) { if (!myIsolatedStorageFile.DirectoryExists("MyFolder"))//如果不存在文件夹“MyFolder” { myIsolatedStorageFile.CreateDirectory("MyFolder");//创建文件夹 } if (myIsolatedStorageFile.FileExists("MyFolder\\content.txt")) { using (IsolatedStorageFileStream myFileStream = myIsolatedStorageFile.OpenFile("MyFolder\\content.txt", FileMode.Open, FileAccess.Read)) { using (StreamReader myReader = new StreamReader(myFileStream)) { while (myReader.Peek() > 0)//判断是不是到了尾部 { Content=myReader.ReadToEnd(); } } } } } }
5.在Application_Deactivated与Application_Closing方法中添加SaveToFile方法,在Application_Activated方法和Application_Launching方法中添加ReadFromFile方法。
// 应用程序启动(例如,从“开始”菜单启动)时执行的代码 // 此代码在重新激活应用程序时不执行 private void Application_Launching(object sender, LaunchingEventArgs e) { ReadFromFile(); } // 激活应用程序(置于前台)时执行的代码 // 此代码在首次启动应用程序时不执行 private void Application_Activated(object sender, ActivatedEventArgs e) { ReadFromFile(); } // 停用应用程序(发送到后台)时执行的代码 // 此代码在应用程序关闭时不执行 private void Application_Deactivated(object sender, DeactivatedEventArgs e) { SaveToFile(); } // 应用程序关闭(例如,用户点击“后退”)时执行的代码 // 此代码在停用应用程序时不执行 private void Application_Closing(object sender, ClosingEventArgs e) { SaveToFile(); }
6.在MainPage.xaml.cs中构建这样的代码:
private string myContent;// 构造函数 public MainPage() { InitializeComponent(); LoadContent(); } private void LoadContent() { (Application.Current as App).ReadFromFile(); myContent=(Application.Current as App).Content; if (myContent != "") { this.myInfo.Text = myContent; } }
最后在Application_Load事件中添加LoadContent方法的调用。最后的执行效果:
关闭或退出后重新进入之后: