Search code examples
c#windows-phone-8windows-phone-8.1

Can conventional File.CreateText(path) be used instead of IsolatedStorageFile?


Seems everyone assumes you have to use Isolated Storage on Windows Phone 8, but I haven't found the why. I've also used some code I was porting, and conventional File.CreateText(Windows.ApplicationModel.Package.Current.InstalledLocation) seems to work fine.

So in code, everyone seems to be doing this (from developer.nokia.com):

IsolatedStorageFile fileStorage = IsolatedStorageFile.GetUserStoreForApplication();
StreamWriter Writer = new StreamWriter(new IsolatedStorageFileStream("TestFile.txt", FileMode.OpenOrCreate, fileStorage));
Writer.WriteLine(textBox1.Text);
Writer.Close();

That's actually exceptionally tame. I've seen too many beginner tutorials that makes that async, and can't figure out why. The above code is presented within a WP7 context, however.


UPDATE: Though the below code worked on WP8 (HTC 8XT) and WP8.1 (Lumia 640) when run from Visual Studio, when I deployed to the store, it blew up immediately when I tried to save to a file.


The below code seems to work just as well, at least on the WP emulator, my HTC 8XT running Windows Phone 8, and my Lumia 640 running WP 8.1. Code below can be seen in marginally better context at this link, but this is the important stuff. Yes, I'm using some hungarian. Sorry. Obviously your page needs to have a TextBox named txtText and a global called strFileLoc.

Windows.ApplicationModel.Package package =
    Windows.ApplicationModel.Package.Current;
Windows.Storage.StorageFolder installedLocation = 
    package.InstalledLocation;
this.strFileLoc = Path.Combine(installedLocation.Path, 
    "myFile.txt");

string strToWrite = this.txtText.Text;
using (StreamWriter sw = File.CreateText(this.strFileLoc))
{
    sw.WriteLine(strToWrite);
    sw.Close();
}

// Load
string strText = string.Empty;
if (File.Exists(this.strFileLoc))
{
    using (StreamReader sr = 
        new StreamReader(File.OpenRead(this.strFileLoc)))
    {
        strText = sr.ReadToEnd();
    }
}
else
{
    strText = "File doesn't exist";
}
this.txtText.Text = strText;

Can this be used in a production app? Why or why not?


Solution

  • The code works while debugging since the VS-based deployment gives your app write access to your install location (an annoying bug / design issue). When your app is deployed from the Store, it doesn't have permissions to the install location and will crash. The solution is to not try and create (or write to) files in your installation folder; use one of your ApplicationData folders instead.

    As to using synchronous vs asynchronous methods, there are two answers. The first answer is that assuming you are making calls from your UI thread, asynchronous methods allow your UI to remain responsive even if the I/O takes a long time (as it might do when loading from an SD card, for example). Relying on synchronous APIs means your UI might glitch or appear to have crashed.

    The second answer is that the System.IO APIs are not valid for Universal apps across Windows 8/8.1, so if you wanted to re-use code you had no choice but to use the ...Async WinRT APIs.

    Starting with Windows 10 Universal apps, you can use System.IO.File again across all Windows device families. And since you can set the current directory, you could do something like this:

    Directory.SetCurrentDirectory(ApplicationData.Current.LocalFolder.Path);
    using (var f = File.CreateText("hello.txt"))
    {
      f.WriteLine("Hello, world");
    }
    

    Note that the current directory is a process-wide setting, so avoid this kind of code in general (setting it in different threads to different values will only result in tears), but it is useful if you have existing code that relies on relative paths. Also note that ideally you would only run code such as the above in a background thread, due to the chance that it will take some time to complete.