05,WP8的文件和存儲


內容預告:

  • 特殊的文件夾(Shared/Media,Shared/ShellContent,Shared/Transfer)
  • 用ISET瀏覽本地文件夾
  • 后台文件傳輸
  • 使用SD存儲卡

但不包括:

  • 本地數據庫(基於LINQ的sqlce)
  • SQLite

本地數據存儲概覽:打包管理器把所有的App放到"安裝文件夾",App存儲數據到"本地文件夾"。

定位存儲位置的不同方式:

WP8文件存儲的備選方案:三種方式

// WP7.1 IsolatedStorage APIs
var isf = IsolatedStorageFile.GetUserStoreForApplication();
IsolatedStorageFileStream fs = new IsolatedStorageFileStream("CaptainsLog.store", FileMode.Open, isf)); ...
// WP8 Storage APIs using URI
StorageFile storageFile = await Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(
new Uri("ms-appdata:
///local/CaptainsLog.store "));
...
// WP8 Storage APIs
Windows.Storage.StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
Windows.Storage.StorageFile storageFile = await localFolder.GetFileAsync("CaptainsLog.store");

用WP7.1的方式:

IsolatedStorage類在System.IO.IsolatedStorage命名空間里:

  • IsolatedStorage,在獨立存儲區表達文件和文件夾
  • IsolatedFileStream,在IsolatedStorage中暴露一個文件流到文件存儲。
  • IsolatedStorageSettings,以鍵值對(Dictionary<TKey,TValue>)方式存儲。

保存數據:

private void saveGameToIsolatedStorage(string message)
{
  using (IsolatedStorageFile isf =
         IsolatedStorageFile.GetUserStoreForApplication())
  {
    using (IsolatedStorageFileStream rawStream = isf.CreateFile("MyFile.store"))
    {
       StreamWriter writer = new StreamWriter(rawStream);
       writer.WriteLine(message); // save the message
       writer.Close();
    }
  }
}

讀取數據:

private void saveGameToIsolatedStorage(string message)
{
  using (IsolatedStorageFile isf =
         IsolatedStorageFile.GetUserStoreForApplication())
  {
    using (IsolatedStorageFileStream rawStream = isf.CreateFile("MyFile.store"))
    {
       StreamWriter writer = new StreamWriter(rawStream);
       writer.WriteLine(message); // save the message
       writer.Close();
    }
  }
}

保存鍵值對數據:記着在最后調用Save函數保存。

void saveString(string message, string name)
{
   IsolatedStorageSettings.ApplicationSettings[name] =
     message;

    IsolatedStorageSettings.ApplicationSettings.Save();
}

讀取鍵值對數據:記着要先檢查是否有這個鍵,否則要拋異常。

string loadString(string name)
{
  if (IsolatedStorageSettings.ApplicationSettings.Contains(name))
  {
      return (string)
           IsolatedStorageSettings.ApplicationSettings[name];
    }
    else
        return null;
}

WinPRT的存儲方式:在Windows.Storage命名空間下:

  • StorageFolder
  • StorageFile
  • 不支持ApplicationData.LocalSettings,只能用IsolatedStorageSettings或自定義文件

用StorageFolder保存數據:

private async void saveGameToIsolatedStorage(string message)
{
     // Get a reference to the Local Folder
     Windows.Storage.StorageFolder localFolder =          Windows.Storage.ApplicationData.Current.LocalFolder;

    // Create the file in the local folder, or if it already exists, just open it
    Windows.Storage.StorageFile storageFile = 
                await localFolder.CreateFileAsync("Myfile.store",                           CreationCollisionOption.OpenIfExists);

    Stream writeStream = await storageFile.OpenStreamForWriteAsync();
    using (StreamWriter writer = new StreamWriter(writeStream))
    {
        await writer.WriteAsync(logData);
    }}

讀取數據:

private async void saveGameToIsolatedStorage(string message)
{
     // Get a reference to the Local Folder
     Windows.Storage.StorageFolder localFolder =          Windows.Storage.ApplicationData.Current.LocalFolder;

    // Create the file in the local folder, or if it already exists, just open it
    Windows.Storage.StorageFile storageFile = 
                await localFolder.CreateFileAsync("Myfile.store",                           CreationCollisionOption.OpenIfExists);

    Stream writeStream = await storageFile.OpenStreamForWriteAsync();
    using (StreamWriter writer = new StreamWriter(writeStream))
    {
        await writer.WriteAsync(logData);
    }}

ms-appdata:/// or ms-appx:/// 保存文件:

// There's no FileExists method in WinRT, so have to try to open it and catch exception instead
  StorageFile storageFile = null;
  bool fileExists = false;

  try  
  {
    // Try to open file using URI
    storageFile = await StorageFile.GetFileFromApplicationUriAsync(
                    new Uri("ms-appdata:///local/Myfile.store"));
    fileExists = true;
  }
  catch (FileNotFoundException)
  {
    fileExists = false;
  }

  if (!fileExists) 
  {
    await ApplicationData.Current.LocalFolder.CreateFileAsync("Myfile.store",CreationCollisionOption.FailIfExists); 
  }
  ...

Windows 8 與 Windows Phone 8 兼容性:

  • WP8下所有的數據存儲用LocalFolder(等效於WP7.1下的IsolatedStorage)
  • 不支持漫游數據:ApplicationData.Current.RoamingFolder
  • 臨時數據:ApplicationData.Current.RoamingFolder
  • 本地鍵值對:ApplicationData.Current.LocalSettings
  • 漫游鍵值對:ApplicationData.Current.RoamingSettings
  • 在Windows8下,可以在用下以代碼在XAML元素里加載AppPackages里的圖片:
    RecipeImage.Source = new System.Windows.Media.Imaging.BitmapImage(           
    new Uri(@"ms-appx:///Images/french/French_1_600_C.jpg", UriKind.RelativeOrAbsolute));

    在Windows Phone8下,不支持這個URI的語法。只能像Windows Phone7.1那樣:

    RecipeImage.Source = new System.Windows.Media.Imaging.BitmapImage("/Images/french/French_1_600_C.jpg");

     

本地文件夾:所有讀寫的I/O操作僅限於本地文件夾(Local Folder)

 保留文件夾:除一般的存儲之外,本地文件夾還用於一些特殊場景:

  • Shared\Media,顯示后台播放音樂的藝術家圖片。
  • Shared\ShellContent,Tiles的背景圖片可以存在這。
  • Shared\Transfer,后台文件傳輸的存儲區域。


數據的序列化:有關數據的持久化

在啟動時,從獨立存儲反序列化。
休眠和墓碑時,序列化並持久存儲到獨立存儲。
激活時,從獨立存儲反序列化。
終止時,序列化並持久存儲到獨立存儲。

為什么序列化:

序列化可以讓內存中的數據集持久存儲到文件中,反序列化則可以將文件中的數據讀取出來。可以用以下方式做序列化:

  • XmlSerializer
  • DataContractSerializer
  • DataContractJsonSerializer
  • json.net等第三方工具

 DataContractSerializer做序列化:

public class MyDataSerializer<TheDataType>
    {
        public static async Task SaveObjectsAsync(TheDataType sourceData, String targetFileName)
        {
            StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync(
                targetFileName, CreationCollisionOption.ReplaceExisting);
            var outStream = await file.OpenStreamForWriteAsync();

            DataContractSerializer serializer = new DataContractSerializer(typeof(TheDataType));
            serializer.WriteObject(outStream, sourceData);
            await outStream.FlushAsync();
            outStream.Close();
        }

        ...    }

用的時候:

List<MyDataObjects> myObjects = ...     
await MyDataSerializer<List<MyDataObjects>>.SaveObjectsAsync(myObjects, "MySerializedObjects.xml");

DataContractSerializer反序列化:

public class MyDataSerializer<TheDataType>
    {
        public static async Task<TheDataType> RestoreObjectsAsync(string fileName)
        {
            StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync(fileName);
            var inStream = await file.OpenStreamForReadAsync();

            // Deserialize the objects. 
            DataContractSerializer serializer =
                new DataContractSerializer(typeof(TheDataType));
            TheDataType data = (TheDataType)serializer.ReadObject(inStream);
            inStream.Close();

            return data;
        }
        ...    }

用的時候:

List<MyDataObjects> myObjects
    = await MyDataSerializer<List<MyDataObjects>>.RestoreObjectsAsync("MySerializedObjects.xml");

SD卡存儲:必須先在application manifest文件中鈎選ID_CAP_REMOVABLE_STORAGE,但不能寫文件進去,且只能讀取APP注冊了的文件關聯類型。

聲明文件類型關聯:WMAppManifest.xml文件中,在Extensions下添加一個FileTypeAssociation元素,Extensions必須緊張着Token元素,且FiteType的ContentType屬性是必須的。

<Extensions>  
<FileTypeAssociation Name=“foo" TaskID="_default" NavUriFragment="fileToken=%s">   
<SupportedFileTypes> <FileType ContentType="application/foo">.foo </FileType> </SupportedFileTypes> </FileTypeAssociation> </Extensions>

讀取SD卡的API:

 


配額管理:Windows Phone里沒有配額。應用自己必須小心使用空間。除非需要,否則不要使用存儲空間,而且要告訴用戶用了多少。定時刪除不用的內容,並考慮同步或歸檔數據到雲服務上。

同步和線程:當狀態信息是復雜的對象時,可以簡單地序列化這個對象,序列化可能會比較慢。將加載和保存數據放在一個單獨的線程里,以保證程序的可響應性。

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM