檔案讀寫對 .NET 開發者而言並不陌生,這是資料儲存與處理的基礎操作。然而在 Windows Store 應用程式開發中,由於安全性與權限機制的限制,我們無法像傳統桌面應用那樣「自由」存取任意路徑。這項限制雖然看似束縛,實則是為了適應行動裝置平台的安全模型——若您需要完整的檔案系統存取權限,傳統桌面應用程式(如 WPF、Windows Forms)或許更適合。
在商店應用中,主要操作兩類目錄:應用程式資料資料夾與使用者文件庫。系統提供 ms-appx:// 與 ms-appdata:// 等特殊 URI 配置,但開發者無需死記這些路徑,透過 Windows.Storage.ApplicationData.Current 即可輕鬆取得對應的 StorageFolder 物件。
於 Visual Studio 中新增「空白應用程式 (Windows)」專案,名稱為 App1。
<Page x:Class="App1.MainPage"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<RichTextBlock Margin="15">
<Paragraph FontSize="24">
<Span>本地儲存目錄:</Span>
<Run x:Name="rnLocal"/>
<LineBreak/><LineBreak/>
<Span>漫遊儲存目錄:</Span>
<Run x:Name="rnRoaming"/>
<LineBreak/><LineBreak/>
<Span>暫存目錄:</Span>
<Run x:Name="rnTemp"/>
</Paragraph>
</RichTextBlock>
</Grid>
</Page>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
this.rnLocal.Text = Windows.Storage.ApplicationData.Current.LocalFolder.Path;
this.rnRoaming.Text = Windows.Storage.ApplicationData.Current.RoamingFolder.Path;
this.rnTemp.Text = Windows.Storage.ApplicationData.Current.TemporaryFolder.Path;
}
執行結果將顯示這三個目錄皆位於 %UserProfile%\AppData\Local\Packages\<PackageName> 下,結構清晰且隔離性佳。
最簡單的方式是使用靜態類別 Windows.Storage.FileIO 或 PathIO,提供非同步的 WriteTextAsync、ReadTextAsync 等方法。
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox x:Name="txtInput" Margin="13" Grid.Row="0" TextWrapping="Wrap"/>
<StackPanel Orientation="Horizontal" Margin="14,10" Grid.Row="1">
<Button FontFamily="Segoe UI Symbol" FontSize="25" Click="onWrite">
<Button.Content>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="tbSob" Grid.Column="0" Text=""/>
<TextBlock Grid.Column="1" Text="寫入檔案"/>
</Grid>
</Button.Content>
</Button>
<Button Margin="16,0,0,0" FontFamily="Segoe UI Symbol" FontSize="25" Click="onRead">
<Button.Content>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="從檔案讀取"/>
<TextBlock Grid.Column="1" Text="{Binding ElementName=tbSob,Path=Text}" RenderTransformOrigin="0.5,0.5">
<TextBlock.RenderTransform>
<RotateTransform Angle="180"/>
</TextBlock.RenderTransform>
</TextBlock>
</Grid>
</Button.Content>
</Button>
</StackPanel>
<TextBlock x:Name="txtRead" Grid.Row="2" Margin="15" TextWrapping="Wrap" FontSize="24"/>
</Grid>
private async void onWrite(object sender, RoutedEventArgs e)
{
if (string.IsNullOrWhiteSpace(this.txtInput.Text)) return;
var local = Windows.Storage.ApplicationData.Current.LocalFolder;
var myFile = await local.CreateFileAsync("my.txt");
if (myFile != null)
{
await Windows.Storage.FileIO.WriteTextAsync(myFile, this.txtInput.Text);
var dlg = new Windows.UI.Popups.MessageDialog("寫入成功。");
await dlg.ShowAsync();
}
}
private async void onRead(object sender, RoutedEventArgs e)
{
string msg = string.Empty;
try
{
var local = Windows.Storage.ApplicationData.Current.LocalFolder;
var file = await local.GetFileAsync("my.txt");
if (file != null)
{
this.txtRead.Text = await Windows.Storage.FileIO.ReadTextAsync(file);
msg = "讀取完成。";
}
}
catch (Exception ex) { msg = ex.Message; }
var dlg = new Windows.UI.Popups.MessageDialog(msg);
await dlg.ShowAsync();
}
若需存取「我的文件」、「圖片」、「音樂」等使用者已知資料夾,可使用 Windows.Storage.KnownFolders 類別。但不同於應用程式資料區,這裡涉及使用者隱私,必須在封裝清單 (Package.appxmanifest) 中宣告權限:
.tmd)。<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<StackPanel Margin="20">
<TextBox x:Name="txtInput" TextWrapping="Wrap" Height="320" FontSize="20"/>
<Button Content="儲存到文件庫" Margin="8,10,0,0" Padding="12,7" FontSize="25" Click="onSaveDoc"/>
</StackPanel>
</Grid>
private async void onSaveDoc(object sender, RoutedEventArgs e)
{
if (string.IsNullOrWhiteSpace(this.txtInput.Text)) return;
var myDocuments = Windows.Storage.KnownFolders.DocumentsLibrary;
var tmdFile = await myDocuments.CreateFileAsync("Data.tmd");
if (tmdFile != null)
{
string strInfo = string.Empty;
try
{
await Windows.Storage.FileIO.WriteTextAsync(tmdFile, this.txtInput.Text);
strInfo = "已寫入文件。";
}
catch (Exception ex) { strInfo = ex.Message; }
var dlg = new Windows.UI.Popups.MessageDialog(strInfo);
await dlg.ShowAsync();
}
}
Windows 8 應用的檔案存取雖有沙箱限制,但透過 ApplicationData 與 KnownFolders API,開發者仍能安全、直觀地完成本地持久化、漫遊同步及使用者文件庫互動。掌握非同步模式與清單宣告機制,是開發高品質 Store 應用的關鍵。