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 the Xamarin form code to multiple platforms. All the mobile platforms have their own file system like read, write, delete files. 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 with 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 is 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 a 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 a new Xamarin Form Application here.
 
 
Add PCLStorage Nuget Package
 
Add the 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 the 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 the 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 the 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 a 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.