Windows Phone 8 - 練習操作Storages

Windows Phone 8 - 練習操作Storages

在<Windows Phone 8 – Storages的轉變>介紹了WP OS 7.1與WP OS 8在Storage分別支援與不支援的項目,WP 7.1依賴

IsolatedStorageFile、IsolatedStorageSettings可參考<Windows Phone 7 – 開發前必懂的事 – Isolated Storage>。

WP 8 SDK除了一樣支援這二個項目之外,也增加了新的APIs:StorageFile、StorageFolder、ExtensionStorageDevice、

Win32 APIs…等,以下便加以說明這些新APIs的特性與使用範例。

 

該篇介紹如何使用StorageFile、StorageFolder存取Local folder或Installation folder,或搭配ExtensionStorageDevice來應用。

首先,先了解這些APIs的使用方式與特性。

 

Windows.Stroage

     該命名空間主要提供管理檔案、資料夾與應用程式設定。以下針對WP8常見的成員舉例說明,如下:

‧Classes

Class Description
ApplicationData 提供連結至Application data store。
KnownFolders 提供連結至常見的位置,包括user content。包括:user’s local libraries(如:Pictures, Documents, Music, or Videos)、remove devices, HomeGroup與Media server devices。
StorageFolder 操作資料夾與內部內容物,並提供相關資訊。
StorageFile 呈現檔案,提供資訊、內容與操作檔案。
StorageStreamTransaction 呈現一個可寫入的Stream。
StreamedFileDataRequest 呈現一個sequential-access output stream,以符合StorageFile進行CreateStreamedFileAsync或ReplaceWithStreamedFileAsync的請求以取得Stream。

      上述的這些類型,其中除了KnownFolders之外,其他均是比較常用的類別;

 

‧Delegates

Delegate Description
StreamedFileDataRequestedHandler 用於應用程式定義第一次透過StorageFile讀取檔案,並且以Stream被存取。

 

‧Enumerations

Enumeration Description
ApplicationDataCreateDisposition 指定應用程式data containers中的建立選項。
ApplicationDataLocality 指定應用程式data store的類型。
CreationCollisionOption 指定如果所需的檔案名稱已存在現有的目錄,要採用那種動作。
FileAccessMode 指定連結檔案的使用模式。
FileAttributes 描述系統檔案或目錄的屬性。
NameCollisionOption 指定如果檔案或目錄重新命名、移動或複製時,遇到在指定位置裡檔案或目錄已存相同名稱時,要採用那種動作。
StorageDeleteOption 指定被刪除的項目是否送至Recycle Bin或永久刪除。
StorageItemTypes 描述實現IStorageItem介面的類別的實例物件。
StreamedFileFailureMode 表示data無法被Streamed的原因。

 

‧Interface

Interface Description
IStorageFile 表示一個檔案。提供相關該檔案的資訊與內容,以及操作它的方法。
IStorageFolder 代表一個目錄。提供操作該目錄、取得內容與相關的資訊。
IStorageItem 代表操作storage items(file or folder)與它們的內容、資訊。
IStorageItemProperties 提供連結IStorageItem的常見與一般屬性。
IStreamedFileDataRequest 代表透過CreateStreamFileAsync()或ReplaceWithStreamFileAsync()方法,請求讀取一個sequential-access(順序存取)StorageFile的Stream。

 

上述介紹了WP8支援Windows.Storage的處理元件,其內容來自MSDN的說明,如果沒有實際用過比較難以操作與了解。

往下針對要使用的StorageFolder與StorageFile加以說明:

 

〉操作StorageFolder與StorageFile來存取Installation Folder與Local Folder下的檔案與目錄

     WP 8在操作File與Folder大部分會透過:StorageFolder與StorageFile類別,當然過去的IsolatedStorage也可以使用,

但由於這二個Storage的處理方式均透過async的方式,因此,在以下範例會很常看到aysnc與await的使用:

 

(A) StorageFolder

     在WP 8裡要存取local folder或是install folder時,配合Protocol使用StorageFolder來取得目標的存取目錄,

再使對應的methods來進行裡面的操作。重要的存取Files與Folders的APIs:

方法 說明
CreateFileQuery() 在local folder建立一個目錄;
CreateFileAsync(String) 在folder或folder group採用非同步的方式建立一個檔案;
CreateFileAsync(String, CreationCollisionOption) 在current folder建立一個新的檔案,並且指定CreationCollisionOption,識別如果如果有存在相同檔名要如何處理。
DeleteAsync() 刪除現在資料夾或File group。
DeleteAsync(StorageDeleteOption) 刪除現在資料夾或File group,可選擇是否要永久刪除。
GetFileAsync 根據指定的檔案名稱,取得目前目錄中的單一檔案。
GetFilesAsync() 取得目前目錄中top-level files。
GetFilesAsync(CommonFileQuery) 取得目前目錄與子目錄中所有檔案清單(list)。檔案的過濾與儲存基於特定的CommonFileQuery。
GetFolderAsync 透過指定的目錄名稱,取得目前目錄中的單一子目錄。
GetFoldersAsync() 取得目前目錄下Top-level的子目錄清單。
GetFoldersAsync(CommonFolderQuery) 取得目前目錄中,所有檔案的StorageFolder集合。檔案透過CommandFolderQuery進行過濾或群組歸類。
GetFolderFromPathAsync 透過指定的file-system path取得該目錄中的StorageFile物件。
RenameAsync(String) 重新命名目前的目錄。
RenameAsync(String, NameCollisionOption) 重新命名目前的目錄,並指定如果遇到相同的名稱的目錄時,該如何處理。

以上是介紹幾個常用的方法,例如:建立目錄、取得目錄清單、取得檔案清單…等,這些均是在操作StorageFolder必要懂

的部分,其中是CommonFolderQuery是一個特別的部分,下方將會進行補充。

 

[注意]

‧使用GetFolderAsync()或GetFileAysnc()時,如果指定的destname無法找到的話,執行緒會直接拋出Exception,而不是給null

 

‧相關StorageFolder可用屬性的部分:

屬性 類型 描述
Attributes Read-only 取得目前資料夾的所有屬性。
DateCreated Read-only 取得目前資料夾被建立的日期與時間。
DisplayName Read-only 取得目前資料夾的顯示名稱(user-friendly name)。
DisplayType Read-only 取得目前資料夾或file group的類型(user-friendly type)。
FolderRelatived Read-only 取得目前資料夾的識別值。這個ID是唯一的,它包含了現在目前資料夾、file group或是來自查詢的結果,並且可以用來區分具有相同名稱的項目。
Name Read-only 取得目前資料夾的名稱。
Path Read-only 取得目前資料夾的full file-system path。前提是資料夾有Path。
Properties Read-only 取得目前資料夾的訪問對象,該對象提供當前資料夾的內容與相關屬性。

了解了StorageFolder的重點方法與相關屬性後,接下來是StorageFile的介紹。

 

StorageFile

     代表一個檔案。該類別提供描述檔案的資訊、內容與操作它的方法。以下介紹幾個重要的方法與屬性:

方法/屬性 說明
CopyAndReplaceAsync 利用特定的檔案複製且取代現有的檔案;
CopyAsync(IStorageFolder, String, NameCollisionOption) 在指定的目錄利用指定名稱建立一個複製的檔案。該方法也指定當遇到目錄有存在相同檔名的檔案時,要怎麼處理。
CreateStreamedFileAsync 將特定的stream of data建立成一個StorageFile。這方法讓應用程式可依需求(on-demand)的在檔案第一次被連結時,產生對應的Stream。
CreateStreamedFileFromUriAsync 利用特定的Uniform Resource Identifier (URI) resource將stream of data建立成一個檔案。
DeleteAsync(StorageDeleteOption) 刪除現在的檔案,選擇是否要永遠刪除。
GetBasicPropertiesAsync 取得現在檔案的基本屬性。
GetFileFromApplicationUriAsync 利用特定的Uniform Resource Identifier (URI) app resource取得StorageFile物件。
GetFileFromPathAsync 取得StorageFile物件,並表示該檔案的指定路徑。
MoveAsync(IStorageFolder, String, NameCollisionOption) 移動現在的檔案至指定的目錄,並且重新命名目的名稱。這方法也設定了當移動到的目錄存在相同的檔案名稱,要如何處理。
MoveAsync(IStorageFolder, String) 移動現有勢檔案至指定的目錄,並且重新命名目的名稱。
OpenAsync 開啟指定檔案為random-access stream。
OpenReadAsync 開啟指定檔案為一個random-access stream,專用於讀取檔案的內容。
OpenSequentialReadAsync 開啟指定檔案為一個sequential-access stream,專用於讀取檔案的內容。
OpenTransactedWriteAsync 開始指定檔案為一個random-access stream,而且可以被使用於transacted-write operations上。
RenameAsync(String) 重新命名目前的檔案。
RenameAsync(String, NameCollisionOption) 重新命名目前的檔案,並且指定在目前目錄有相同的檔案名稱,要怎麼處理。
ReplaceWithStreamedFileAsync 用一個新的Stream取代指定的StorageFile。This method lets the app produce the data on-demand by specifying a function to be invoked when the StorageFile that represents the stream is first accessed.
ReplaceWithStreamedFileFromUriAsync 用一個新的Uniform Resource Identifier (URI)所取得的Stream,取代指定的StorageFile。This method lets the app download the data on-demand when the StorageFile that represents the stream is first accessed.

 

‧相關StorageFile的屬性,可參考下方的列表:

屬性 類型 描述
Attribute Read-only 取得目前檔案的所有屬性。
ContentType Read-only 取得目前檔案內容的MIME Type。
DateCreated Read-only 取得目前檔案被建立的日期與時間。
DisplayName Read-only 取得目前檔案的顯示名稱(user-friendly name)。
DispayType Read-only 取得目前檔案的描述類型(user-friendly description)。
FileType Read-only 取得目前檔案的類型(file name extension)。
FolderRelatived Read-only 取得目前檔案的識別值。該ID是唯一的,可用於查詢的結果或StorageFile代表用來識別具有相同名稱時不同的檔案。
Name Read-only 取得目前檔案的完整名稱,包括副檔名。
Path Read-only 取得目前檔案的full file-system path。
Properties Read-only 取得目前檔案的訪問對象,提供內容與相關屬性。

以上是介紹StorageFiled的相關屬性,在了解了StorageFolder與StorageFile之後,往下便開始透過程式的範例加以說明。

 

[範例說明]

(1) 撰寫一個將TextBox的內容,寫入一個新的檔案與讀取該檔案的功能

       1-1. 撰寫產生新的檔案的邏輯

   1: /// <summary>
   2: /// 寫入檔案。
   3: /// </summary>
   4: /// <returns></returns>
   5: private async Task WriteToFile()
   6: {
   7:     // 將輸入於TextBox中的內容,轉成byte[]準備成為Stream寫入
   8:     byte[] fileBytes = System.Text.Encoding.UTF8.GetBytes(this.textBox1.Text.ToCharArray());
   9:     // 取得Local Folder的根目錄
  10:     StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;
  11:     // 建立一個test.txt的檔案,並且指定如果遇到同名稱檔案將它覆寫
  12:     var file = await local.CreateFileAsync("test.txt",
  13:                            CreationCollisionOption.ReplaceExisting);
  14:     // 透過StorageFile將檔案非同步使用Stream寫入;
  15:     var s = await file.OpenStreamForWriteAsync();
  16:     s.Write(fileBytes, 0, fileBytes.Length);
  17:     s.Close();
  18: }
  19:  
  20: private async void btnWrite_Click(object sender, RoutedEventArgs e)
  21: {
  22:     //使用一個定義好的async方法,因為用await該方法上要加上async;
  23:     await WriteToFile();
  24:     this.btnWrite.IsEnabled = false;
  25: }

              其中使用了Windows.Storage.ApplicationData.Current.LocalFolder取得StorageFolder來建立實際的StorageFile,

              透過OpenStreamForWriteAsync()取得Stream物件,將字串轉成byte[]寫入檔案;

 

       1-2. 撰寫讀取該檔案的功能

   1: /// <summary>
   2: /// 讀取檔案。
   3: /// </summary>
   4: /// <returns></returns>
   5: private async Task ReadFile()
   6: {
   7:     // 取得Local Folder的根目錄
   8:     StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;
   9:  
  10:     if (local != null)
  11:     {
  12:         // 指定local folder\test.txt開啟檔案為Stream物件
  13:         var file = await local.OpenStreamForReadAsync("test.txt");
  14:         // 透過StreamReader讀取Stream物件
  15:         StreamReader streamReader = new StreamReader(file);
  16:         this.textBlock1.Text = streamReader.ReadToEnd();
  17:         streamReader.Close();
  18:     }
  19: }
  20:  
  21: private async void btnRead_Click(object sender, RoutedEventArgs e)
  22: {
  23:     await ReadFile();
  24:     this.btnWrite.IsEnabled = true;
  25: }

                透過StorageFolder將指定的檔案讀取出來,並且轉成Stream物件,再藉由StreamReader將Stream讀取成字串,

                加以顯示於TextBox上。

 

(2) 撰寫一個存取Installation folder的範例程式

       2-1. 讀取Installation folder中的根目錄,列出有多少個子目錄

   1: private async void btnICreateFolder_Click(object sender, RoutedEventArgs e)
   2: {
   3:     StorageFolder tFolder = null;
   4:     try
   5:     {
   6:         //指定Installation folder的目錄
   7:         tFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
   8:     }
   9:     catch (Exception ex)
  10:     {
  11:         //代表沒有找到指定的Folder
  12:         txtResult.Text = ex.Message;
  13:     }
  14:     if (tFolder != null)
  15:     {
  16:         //取得該目錄下所有的資料夾
  17:         var tFiles = await tFolder.GetFilesAsync();
  18:         txtResult.Text = "共有檔案: " + tFiles.Count().ToString();
  19:     }
  20: }

              透過Windows.ApplicationModel.Package.Current取得InstalledLocation的根目錄,再藉此取得子目錄;

 

     2-2. 讀取Installation folder中Assets/Tiles目錄下的檔案

   1: private async void btnICreateFile_Click(object sender, RoutedEventArgs e)
   2: {
   3:     StorageFolder tFolder = null;
   4:     try
   5:     {
   6:         //透過URI的方式取得指定的檔案
   7:         Uri tUri = new Uri("ms-appx:///Assets/Tiles/FlipCycleTileLarge.png", UriKind.Absolute);
   8:         var tFile = await Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(tUri);
   9:         if (tFile != null)
  10:         {
  11:             //將StorageFile=>Stream=>BitmapImage=>Image
  12:             BitmapImage tBitImg = new BitmapImage();
  13:             Stream tStream = await tFile.OpenStreamForReadAsync();
  14:             tBitImg.SetSource(tStream);
  15:             Image tImgControl = new Image();
  16:             tImgControl.Source = tBitImg;
  17:             LayoutRoot.Children.Add(tImgControl);
  18:         }
  19:     }
  20:     catch (Exception ex)
  21:     {
  22:         //代表沒有找到指定的Folder
  23:         txtResult.Text = ex.Message;
  24:     }
  25: }

               上述範例直接透過URI的方式將檔案讀取成StorageFile,再將轉成Stream放入Bitmap與Image中。

 

[範例程式]

======

以上是分享在於StorageFolder與StorageFile的使用經驗與說明,其實操作起來其實只要懂得使用正確的URI,

或是習慣有File System經驗的開發者,均會覺得比過去只透過IsolatedStorage來的更多豐富的功能。不過我操

作下來熟悉度是個問題。在範例程式裡有補充一些寫法可以參考,希望對大家有所幫助。謝謝。

 

References:

Data for Windows Phone

Reading from the SD card on Windows Phone 8

How to load file resources (Windows Store apps using JavaScript and HTML)

How to: Use the Isolated Storage Explorer Tool

What's new in Windows Phone 8 (重要)

Windows Phone 7 – 開發前必懂的事 – Isolated Storage

 

Dotblogs Tags: