File System Access from the Portable Class Library (PCL)

One fine day, I had the idea of ​​porting my .NET code to other platforms with the transfer of the main logic (everything that does not concern the UI) to a separate Portable Class Library (PCL).

In theory, everything sounds cool - with PCL you can work on almost all devices, and not only with the .NET Framework, but even with Mono! With this approach, great multi-platform prospects open up, for example, porting Windows Phone code to Android and iOS using Xamarin.

But after getting a closer look at PCL, I came to the conclusion that such a library is essentially a stripped down .NET that takes into account the limitations of each platform. That is, even with seemingly similar WP8 and W8, it will not be possible to shove everything into the PCL.

PCL features table on different platforms

At first glance, my code should have passed without problems (target platforms: Windows .NET, Windows 8, Windows Phone), but the compiler scolded System.IO, namely StreamReader, which directly opened the file.

Remembering that Windows 8 and Windows Phone have completely different ways to work with files and are different among themselves:

WP uses IsolatedStorage to access application files, and Windows 8, although it has access to public folders, does it through Windows.Storage (WP8 can now also use it, but this method is not recommended to be used to maintain WP7 support). Using Google, it became clear to me that it was impossible to access files on a pure PCL, and advice like transferring Steam from an application or hard file inclusion in a DLL was not suitable for my solution. The fact is that the program worked with a large external dictionary and saved temporary work results in files. But then the PCLStorage library caught my eye, which promised some kind of work with the FS via PCL.

PCLStorage provides three interfaces - IFIle, IDirectory, IFileSystem, all of which provide asynchronous read and write operations for files and directories.

Note: All further tests were conducted on the "classic" Windows.

Example file record:

 public async Task PCLCreateFile(string name, string content)
            IFolder localStorage = FileSystem.Current.LocalStorage;
            IFolder contentFolder = await localStorage.CreateFolderAsync("Content", CreationCollisionOption.OpenIfExists);
            IFile file = await contentFolder.CreateFileAsync(name, CreationCollisionOption.ReplaceExisting);
            await file.WriteAllTextAsync(content);

Example of reading a file:

      public async Task PCLReadFile(string name)
            IFolder localStorage = FileSystem.Current.LocalStorage;
            IFolder contentFolder = await localStorage.GetFolderAsync("Content");
            IFile file = await contentFolder.GetFileAsync(name);
            return await file.ReadAllTextAsync();

Everything looks and works fine. But ... how to access the file, which is located in the program directory?

IFileSystem returns two paths LocalStorage and RoamingStorage. The first points to the directory that is allocated for the program in the current system, the second to the public directory for data synchronization. In particular, in Windows, LocalStorage pointed to (AppData \ Local), which was far from the application directory and did not contain any files.

Unfortunately, PCLStorage could not point to the application directory.

Of course, it was possible to create a special installer, but what about Store applications? However, a solution appeared - copying files to LocalStorage from the application itself (or downloading from the network in the PCL itself (not tested)). Well, the method eventually turned out to be simpler than the Stream transfer, plus it became possible to work with temporary files in a limited environment of a portable library.

PS: At the end of the experiment, it turned out that WP7 support was thrown out of the latest version, which is why everything was actually started (due to the separate use of IsolatedStorage on WP and Windows.Storage on Windows 8).

Also popular now: