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: