File IO in Windows 8 14 October 2011 Michael-Van-Wesemael Windows 8, XAML, Metro Let’s leave Windows Phone for a moment, and let’s have a look at Windows 8. Recently the U2U-team was present at the Microsoft Build-convention in Anaheim, California, where Microsoft unveiled Windows 8. Now, what we saw is still just a preview, but it clearly shows the direction in which Windows is evolving. Have a look at this video, to see Windows 8 in action : The “new style” applications Windows 8 offers are “Metro”-applications (yes, like in Windows Phone Metro style), and these can be made using Xaml and managed code, or even using HTML5 + Javascript. Metro-apps will have to be installed through a marketplace, and are kind of sandboxed (Comparable to Silverlight, but different ;-) ). One of the effects of this sandboxing is that your options for working with files are limited. You cannot just access any folder on your machine ! Unfortunately you’re also unable to use Isolated Storage. So what can you use ? Let’s start by writing info into the “Local Folder”. Windows.Storage.ApplicationData appData = Windows.Storage.ApplicationData.Current; StorageFile file = await appData.LocalFolder.CreateFileAsync("EmployeeList.u2u"); Windows.Storage.Streams.IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite); .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } No ordinary File here, but a StorageFile which I have to open to write in. The IRandomAccessStream I get back gives me the possibility to create an input- (for reading) or output-stream (for writing). IOutputStream output = stream.GetOutputStreamAt(0); .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } And then I got stuck. The IOutputStream gives me a WriteAsync-function, but it ask me for an IBuffer-object. How to write data ? Luckily there’s already some MSDN-documentation available. That tells me to use a DataWriter which takes the IOutputStream as a constructor-argument. DataWriter writer = new DataWriter(output); writer.WriteString("HERE GOES DATA"); output.FlushAsync(); .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Not there yet ! The code I wrote starts fro; the assumption that File IO is much like the “ordinary” file IO: flush the stream and done. In Metro we have to ”commit” the data in the writer, and I have to start the flushing, so this is the working code : 1: DataWriter writer = new DataWriter(output); 2: writer.WriteString("HERE GOES DATA"); 3: 4: await writer.StoreAsync(); 5: output.FlushAsync().Start(); 6: statusTxt.Text = "File Saved"; .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } They could have made it simpler . By localfolder I assumed the bin/debug-folder. Nothing there. It seems my file is located in C:\Users\michael\AppData\Local\Packages\d64899f1-9800-470a-9cb3-fa89210f4941_qs0a8q7rnpy8j\LocalState. How about reading the file ? Well, simply reverse your writing-logic (writer becomes reader, output becomes input, store becomes load, …) 1: Windows.Storage.ApplicationData appData = Windows.Storage.ApplicationData.Current; 2: 3: var file = await appData.LocalFolder.GetFileAsync("EmployeeList.u2u"); 4: Windows.Storage.Streams.IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read); 5: 6: IInputStream input = stream.GetInputStreamAt(0); 7: 8: DataReader reader = new DataReader(input); 9: 10: var size = stream.Size; 11: await reader.LoadAsync((uint)size); 12: var data = reader.ReadString((uint)size); .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } There you go! What about other folders than the “local” ? The KnownFolders=clqss gives me access to following locations : Documents Library Home Group Media Server Devices (DLNA – Digital Living Network Alliance Devices, sounds interesting) MusicLibrary Pictures Library Removable Devices Videos Library Let’s change the first 2 lines of my writing-code for using the documents library : StorageFolder doclib = Windows.Storage.KnownFolders.DocumentsLibrary; StorageFile file = await doclib.CreateFileAsync("EmployeeList.u2u"); .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } As soon as you start running your code, it will fail on the first line (no exception though, simply stops). That’s because you explicitly have to give the app the capability to access the Document library. Double-clicking on Package.appxmanifest allows you to do that : Still: this time your app will stop on the second line. You also need to associate your app with the u2u-fileextension. This is also done in the appxmanifest-file in the declarations-tab where we add a filetype association declaration : There you go: the app works and saves my u2u-file in the doclibrary. Tweet