Jerry Nixon on Windows

Friday, June 29, 2012

Windows 8: The right way to Read & Write Files in WinRT

Windows 8 Store Apps leverage WinRT; and, in WinRT, there are new namespaces – and namespace constriction in the .Net Framework. What you think you know, you may not.

MSDN: In some cases, a type that you used in a .NET Framework desktop app doesn't exist within the .NET APIs for Windows Store Apps. Instead, you can use a type from the Windows Runtime. For example, the System. IO. IsolatedStorage. IsolatedStorageSettings class isn't included in the .NET APIs for Windows Store Apps, but the Windows.Storage.ApplicationDataContainer class provides similar behavior for storing app settings. Examples of common changes you might have to make are included in the section Converting your existing .NET Framework code.

Read Isolated Storage

Every Windows Store App has three folders. A Local folder, a Roaming folder and a Temp folder. Each is accessed the same way. Local is meant to store assets in a local, application-specific folder.

To request that Windows index your app data for search, create a folder named "indexed" under this folder and store the files that you want indexed there. Windows indexes the file content and metadata (properties) in this "indexed" folder and all its subfolders.

Roaming is meant to store assets that should be synchronized with any other desktop where the current user has the same application installed.

MSDN: The sync engine has restrictions on the file name conventions that you must follow to ensure the items in the roaming folder can roam. Be sure that your file and folder names do not contain leading whitespace. The sync engine may limit the total size of settings and files that can roam. You can access files in the roaming app data store using the "ms-appdata:///roaming/" protocol.

<img src="ms-appdata:///roaming/myFile.png" alt="" />

Temp is a throw-away location that will be cleaned, potentially, every time the application is launched.

MSDN: You can access files in the temporary app data store using the "ms-appdata:///temp/" protocol.

Here’s how you use them:

The code above is a simple Unit Test demonstrating the core functionality of writing and reading to Isolated Storage. You might notice that there is no mention of Isolated Storage in the code or namespaces (like there is in the Windows Phone API). Just know that all of this takes place in Isolated Storage, and for the same reason – to compartmentalize your application and it’s ability to break the user’s machine.

Read Project Files

Here’s a fun one. What if you have a resource (a file) in your project that you want to read? Lots of time this is for sample data or settings or something. It could be an XML file, a JSON file, or something else. Can you do it? Of course.

Step 1

Add the file to your project. Note: since this is your file, you will need to deal with the type. Somewhere else you can learn how to deserialize JSON and XML.

Step 2

Change your file’s Build Action to Content. And, change Copy to Output Directory to Copy Always. This will ensure the file itself ships with your application. If it doesn’t, you wont have a file to read!

Step 3

Read your project file like this:

Note: the following code was updated June 2013. Prior to this update, it contained a bug that dealt with Windows 8 Developer Preview. This code is now correct. Sorry for the confusion.

The code above is a simple Unit Test demonstrating how to read a file that is included in your project’s folder structure. The two most important parts is the unique path and Installed Location folder. Pay close attention. The correct path will include your project name (mine is Metro.Helpers.Tests).

Read Local files w/a Picker

Here’s a great one. You want to read a file in the Documents Library? Let the user select the file using a picker, and take it from there! Let’s do it.

Just do it

There’s nothing special you have to do in order to use a file picker. No changes to the AppXManifest, I mean. The reason is, using a File Picker puts the user in charge. Only the user can pick a file. And so, the picker itself is sort of its own Capabilities declaration and consent.

In the code above we initialize the FileOpenPicker (just like we have always done in .Net). We invoke the picker using PickSingleFileAsync() where we get a StorageFile (just like all the techniques above)and we go from there. I added a MessageBox (aka MessageDialog) to show some details. Clearly in your application you will do something else.

Read Local files w/o a Picker

Capabilities Tab

Declarations Tab

What if you want to read a file without using the File Picker. Can you do that? You bet. But, it takes more effort because you need to update your applications AppXManifest to request the Document Library Access capability.

But wait there’s more.

See that red X on the Capabilities tab title? That tells you that something is not right. The manifest designer is pretty cool. What’s left?

You also need to update your AppXManifest by declaring what file type(s) you want to access. Then, even with access to the folders, you only have access to a limited set of file types. (in case you wondered *.* is not allowed)

Note: Accessing the file system without user interaction is dangerous for the user. These extra steps are not meant to make your life (the developer) easier. It is meant to make the user’s experience easier and more safe.

So, in my case I will only want access to TXT files. The Declarations tab can be complex – to learn more about it, look here. I set a new file type (.txt) and let it role from there.

When the user installs your application, they will be promoted to consent to the capabilities your application requests. Its capabilities are constrained by the manifest. And, your app’s capabilities are reviewed by Microsoft store curators.

Now, get that file!

You have probably noticed with all the samples in this article that I have to write and read in order to have a reliable test. This one is no different. This will create the HelloWorld.txt file and read it. For added fun, I also will delete the file at the end of the method so your folder is not polluted.

The only reason the code above works is because we have declared the capability to read TXT files from the Documents Library folder in the AppXManifest file. Reading the file is easy because, once you get it, it’s just a simple WinRT StorageFile.

Pretty simple really, eh?

Some interesting StorageFile methods:

CopyAsync()

DeleteAsync()

MoveAsync()

OpenAsync()

RenameAsync()

I might take a moment to talk about StorageFolder, too. One of the most common requests I get is to iterate files and folders on user’s system. You really can’t – if what you mean is to start at c:\. Try to iterate through c:\ and you get this:

You can, however, iterate the files in a Library (Documents, Photos, Music, Videos, and even Home Group) folder – if you have requested this capability in the manifest. It is important to note that the files returned for a folder will be automatically filtered to the file types you declare in your manifest. (Did I already mention *.* cannot be declared?) Let me restate that as a developer you have intentional restrictions like this that ultimately improve the user’s experience and safety.

Conclusion

Read those files people. Whatever your reason, they are there for you to get them. Yes, the sandbox of a Windows Store App prevents access to files and resources outside user’s Libraries. But in about 2 seconds you can appreciate this decision. We are approaching a brave new world.

Now, should your application REQUIRE such access (that is otherwise restricted), you might consider the choice between desktop and Windows Store Apps – or consider a clever alternative; we all know you are a clever developer, keen at problem solving. You can do it!

Hey! I'm Jerry Nixon, a Microsoft Engineer in Colorado. If you are into development, you are at the right place. I blog, I teach, and speak; should you see me out somewhere, say hi! Thanks for your visit.