WinRT: File Access

This post contains my notes from the "File Access" sample in the Windows 8 developer samples.

Let me start by noting that all these samples are designed to show how the API is structured.  These samples do not show proper separation of concerns, or architectural patterns like MVVM. In fact, all the code is in the CodeBehind for the MainWindows.xaml.cs.  Oh well, that’s not what the samples are teaching.

There are two key takeaways from this sample.  First, IO programming in WinRT is very similar to IO programming in the .NET Framework. The addition of the ‘await’ keyword before each call is the only new technique here. Second, Metro applications should not just browse the file system for storage locations.  Each application should restrict its storage to the application specific document library.  The code shows both of these concepts pretty clearly.

The main Window’s Initialize() code initializes a StorageFile object by searching for the file on disc, and creating the associated StorageFile object (asynchronously, of course):

async void Initialize()

{

    try

    {

        sampleFile = await Windows.Storage.KnownFolders.DocumentsLibrary.GetFileAsync("sample.txt");

    }

    catch (FileNotFoundException)

    {

        // 'sample.txt' doesn't exist so scenario one must be run

    }

}

The other file APIs all work in a similar fashion.  Reading a file looks almost exactly like reading a file with the current .NET BCL library:

async void Scenario2ReadText_Click(object sender, RoutedEventArgs e) 

{ 

    if (sampleFile != null) 

    { 

        string fileContent = await FileIO.ReadTextAsync(sampleFile); 

 

        this.Scenario2Output_textblock.Text = "The following text was read from '" + 

 

                sampleFile.Name + "':" + Environment.NewLine + Environment.NewLine + fileContent; 

 

    } 

}

The Streaming APIs are also present, and look quite familiar:

async void Scenario4WriteToStream_Click(object sender, RoutedEventArgs e)

 

{

    if (sampleFile != null)

    {

        string userContent = Scenario4Textbox.Text;

        if (!String.IsNullOrEmpty(userContent))

        {

            using (IRandomAccessStream writeStream = await sampleFile.OpenAsync(FileAccessMode.ReadWrite))

            {

                using (DataWriter dataWriter = new DataWriter(writeStream))

                {

                    dataWriter.WriteString(userContent);

                    await dataWriter.StoreAsync();

                    await dataWriter.FlushAsync();

                    this.Scenario4Output_textblock.Text = "The following text was written to '" +

                        sampleFile.Name + "' using a stream:" + Environment.NewLine + Environment.NewLine +

                        userContent;

                }

            }

        }

        else

        {

            this.Scenario4Output_textblock.Text =

"The text box is empty, please write something and then click 'Write' again.";

        }

    }

}

async void Scenario4ReadFromStream_Click(object sender, RoutedEventArgs e)

{

    if (sampleFile != null)

    {

        using (IRandomAccessStream readStream = await sampleFile.OpenAsync(FileAccessMode.Read))

        {

            using (DataReader dataReader = new DataReader(readStream))

            {

                uint numBytesLoaded = await dataReader.LoadAsync((uint)readStream.Size);

                string fileContent = dataReader.ReadString(numBytesLoaded);

                this.Scenario4Output_textblock.Text = "The following text was read from '"

                    + sampleFile.Name + "' using a stream:" + Environment.NewLine + Environment.NewLine + fileContent;

            }

        }

    }

}

I won’t simply repost the rest of the code. This is enough to ensure that you get the main ideas.  There are two main ideas to get across from this sample:

1. Store your application’s data in the application specific sandbox.

2. Use the familiar IO APIs, but remember that they are async.

Comments are closed.