Local File Storage Using Xamarin.Forms

Introduction

Xamarin.Forms code runs on multiple platforms - each of which has its own file system. We can share most of Xamarin form code to multiple platforms. All the mobile platforms have their own file system like read, write, delete file. We don’t have any direct API for sharing File System, using Xamarin form .

Xamarin recommends third -party component called PCLStorage. We can share our file storage library to all the platforms. There is no need to write it separately.

PCLStorage

PCL Storage provides a consistent, portable set of local file IO APIs for .NET, Windows Phone, Windows Store, Xamarin.iOS, Xamarin.Android and Silverlight. This makes it easier to create cross-platform .NET libraries and apps.



Here is a sample, which shows how you can use PCL Storage to create a folder and write to a text file in the folder.

I have created a sample application and published the Basic Storage Recipes sample, using Xamarin Form. Download the sample to see working examples of the programming tasks.

Here, the list of tasks are demonstrated in the Basic Storage Recipes sample.







In addition to showing you how to work with the files and PCL Storage sample, it also demonstrates the following tasks.

  • Read File
  • Write file
  • Create Folder
  • Check folder and file exists
  • Save Image
  • Read Image
  • Delete File
  • Replace file

Create New Xamarin.Form Application

Xamarin.Forms is a cross platform UI toolkit, which allows the user to efficiently create native user interface layout. The code can be shared with all the devices (IOS, Android, Windows Phone and Win store app). Just refer to my previous article to create new Xamarin Form Application here.



Add PCLStorage Nuget Package

Add PCLStorage Nuget package to all the projects. Right click on Project Solution. Click “Manage NuGet package for Solution “. Search and select “PCLStorage”. Select all the Projects. Click Install.

More about PCLStorage.



Start creating the code from a portable library, as shown below.

Cross platform Local Folder

In Xamarin.Form, the PCLStorage API will help us to retrieve all the platforms'  local folder names and paths, using the code given below. There is no need to write any platform specific code to access the local folder.

  1. Using PCLStorage;  
  2.   
  3. IFolder folder = FileSystem.Current.LocalStorage;  
Creating new folders

To create a new subfolder in the local folder, call the CreateFolderAsync method.
  1. String folderName =”csharp” ;  
  2. IFolder folder = FileSystem.Current.LocalStorage;  
  3. folder = await folder.CreateFolderAsync(folderName, CreationCollisionOption.ReplaceExisting);  
Create New file

To create a new file in the local folder, call the CreateFileAsync method.
  1. String filename=”username.txt”;  
  2. IFolder folder = FileSystem.Current.LocalStorage;  
  3. IFile file = await folder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);  
Check Folder Already Exists

We can check for an existing folder in a particular folder, as shown below.
  1. public async static Task<bool> IsFolderExistAsync(this string folderName, IFolder rootFolder = null)  
  2.      {  
  3.          // get hold of the file system  
  4.          IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;  
  5.          ExistenceCheckResult folderexist = await folder.CheckExistsAsync(folderName);  
  6.          // already run at least once, don't overwrite what's there  
  7.          if (folderexist == ExistenceCheckResult.FolderExists)  
  8.          {  
  9.              return true;  
  10.   
  11.          }  
  12.          return false;  
  13.      }  
Check File Already Exists

We can check for an existing file in a particular folder, as shown below.
  1. public async static Task<bool> IsFileExistAsync(this string fileName, IFolder rootFolder = null)  
  2.         {  
  3.             // get hold of the file system  
  4.             IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;  
  5.             ExistenceCheckResult folderexist = await folder.CheckExistsAsync(fileName);  
  6.             // already run at least once, don't overwrite what's there  
  7.             if (folderexist == ExistenceCheckResult.FileExists)  
  8.             {  
  9.                 return true;  
  10.   
  11.             }  
  12.             return false;  
  13.         }  
Delete File

We can use DeleteAsync method to delete the file.
  1. public async static Task<bool> DeleteFile(this string  fileName, IFolder rootFolder = null)  
  2.       {  
  3.           IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;  
  4.           bool exist = await fileName.IsFileExistAsync(folder);  
  5.           if (exist == true)  
  6.           {  
  7.               IFile file = await folder.GetFileAsync(fileName);  
  8.               await file.DeleteAsync();  
  9.               return true;  
  10.           }  
  11.           return false;  
  12.       }  
Write File

If you want to write any extension file document, just use WriteAllTextAsync method for write.
  1. public async static Task<bool> WriteTextAllAsync(this string filename, string content = "", IFolder rootFolder = null)  
  2.       {  
  3.           IFile file = await filename.CreateFile(rootFolder);  
  4.           await file.WriteAllTextAsync(content);  
  5.           return true;  
  6.       }  
Read File

If you want to read any extension file document, just use ReadAllTextAsync method for write.
  1. public async static Task<string> ReadAllTextAsync(this string fileName, IFolder rootFolder = null)  
  2.      {  
  3.          string content = "";  
  4.          IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;  
  5.          bool exist = await fileName.IsFileExistAsync(folder);  
  6.          if (exist == true)  
  7.          {  
  8.              IFile file = await folder.GetFileAsync(fileName);  
  9.              content = await file.ReadAllTextAsync();  
  10.          }  
  11.          return content;  
  12.      }  
Save Image

We can save the image, using PCLStorage, as shown below.
  1. public async static Task SaveImage(this byte[] image,String fileName, IFolder rootFolder = null)  
  2.         {  
  3.             // get hold of the file system  
  4.             IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;  
  5.   
  6.             // create a file, overwriting any existing file  
  7.             IFile file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);  
  8.   
  9.             // populate the file with image data  
  10.             using (System.IO.Stream stream = await file.OpenAsync(FileAccess.ReadAndWrite))  
  11.             {  
  12.                 stream.Write(image, 0, image.Length);  
  13.             }  
  14.         }  
Get Image

We can load an image, using PCLStorage, as shown below.
  1. public async static Task<byte[]> LoadImage(this byte[] image, String fileName, IFolder rootFolder = null)  
  2.         {  
  3.             // get hold of the file system  
  4.             IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;  
  5.   
  6.             //open file if exists  
  7.             IFile file = await folder.GetFileAsync(fileName);  
  8.             //load stream to buffer  
  9.             using (System.IO.Stream stream = await file.OpenAsync(FileAccess.ReadAndWrite))  
  10.             {  
  11.                 long length = stream.Length;  
  12.                 byte[] streamBuffer = new byte[length];  
  13.                 stream.Read(streamBuffer, 0, (int)length);  
  14.                 return streamBuffer;  
  15.             }  
  16.               
  17.         }  
PCL Helper Class

I have created very simple PCLHelper class. You can refer to it and reuse it in your project.
  1. using PCLStorage;  
  2. using System;  
  3. using System.Threading.Tasks;  
  4.   
  5. namespace DevEnvExe_LocalStorage  
  6. {  
  7.     public static class PCLHelper  
  8.     {  
  9.       
  10.         public async static Task<bool> IsFileExistAsync(this string fileName, IFolder rootFolder = null)  
  11.         {  
  12.             // get hold of the file system  
  13.             IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;  
  14.             ExistenceCheckResult folderexist = await folder.CheckExistsAsync(fileName);  
  15.             // already run at least once, don't overwrite what's there  
  16.             if (folderexist == ExistenceCheckResult.FileExists)  
  17.             {  
  18.                 return true;  
  19.   
  20.             }  
  21.             return false;  
  22.         }  
  23.   
  24.         public async static Task<bool> IsFolderExistAsync(this string folderName, IFolder rootFolder = null)  
  25.         {  
  26.             // get hold of the file system  
  27.             IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;  
  28.             ExistenceCheckResult folderexist = await folder.CheckExistsAsync(folderName);  
  29.             // already run at least once, don't overwrite what's there  
  30.             if (folderexist == ExistenceCheckResult.FolderExists)  
  31.             {  
  32.                 return true;  
  33.   
  34.             }  
  35.             return false;  
  36.         }  
  37.   
  38.         public async static Task<IFolder> CreateFolder(this string folderName, IFolder rootFolder = null)  
  39.         {  
  40.             IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;  
  41.             folder = await folder.CreateFolderAsync(folderName, CreationCollisionOption.ReplaceExisting);  
  42.             return folder;  
  43.         }  
  44.   
  45.         public async static Task<IFile> CreateFile(this string filename, IFolder rootFolder = null)  
  46.         {  
  47.             IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;  
  48.             IFile file = await folder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);  
  49.             return file;  
  50.         }  
  51.         public async static Task<bool> WriteTextAllAsync(this string filename, string content = "", IFolder rootFolder = null)  
  52.         {  
  53.             IFile file = await filename.CreateFile(rootFolder);  
  54.             await file.WriteAllTextAsync(content);  
  55.             return true;  
  56.         }  
  57.   
  58.         public async static Task<string> ReadAllTextAsync(this string fileName, IFolder rootFolder = null)  
  59.         {  
  60.             string content = "";  
  61.             IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;  
  62.             bool exist = await fileName.IsFileExistAsync(folder);  
  63.             if (exist == true)  
  64.             {  
  65.                 IFile file = await folder.GetFileAsync(fileName);  
  66.                 content = await file.ReadAllTextAsync();  
  67.             }  
  68.             return content;  
  69.         }  
  70.         public async static Task<bool> DeleteFile(this string  fileName, IFolder rootFolder = null)  
  71.         {  
  72.             IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;  
  73.             bool exist = await fileName.IsFileExistAsync(folder);  
  74.             if (exist == true)  
  75.             {  
  76.                 IFile file = await folder.GetFileAsync(fileName);  
  77.                 await file.DeleteAsync();  
  78.                 return true;  
  79.             }  
  80.             return false;  
  81.         }  
  82.         public async static Task SaveImage(this byte[] image,String fileName, IFolder rootFolder = null)  
  83.         {  
  84.             // get hold of the file system  
  85.             IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;  
  86.   
  87.             // create a file, overwriting any existing file  
  88.             IFile file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);  
  89.   
  90.             // populate the file with image data  
  91.             using (System.IO.Stream stream = await file.OpenAsync(FileAccess.ReadAndWrite))  
  92.             {  
  93.                 stream.Write(image, 0, image.Length);  
  94.             }  
  95.         }  
  96.   
  97.         public async static Task<byte[]> LoadImage(this byte[] image, String fileName, IFolder rootFolder = null)  
  98.         {  
  99.             // get hold of the file system  
  100.             IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;  
  101.   
  102.             //open file if exists  
  103.             IFile file = await folder.GetFileAsync(fileName);  
  104.             //load stream to buffer  
  105.             using (System.IO.Stream stream = await file.OpenAsync(FileAccess.ReadAndWrite))  
  106.             {  
  107.                 long length = stream.Length;  
  108.                 byte[] streamBuffer = new byte[length];  
  109.                 stream.Read(streamBuffer, 0, (int)length);  
  110.                 return streamBuffer;  
  111.             }  
  112.               
  113.         }  
  114.     }  
  115. }  
I believe this will be helpful for all Xamarin developers. If you have any questions, please post them in the comment box.