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.
- Using PCLStorage;
-
- IFolder folder = FileSystem.Current.LocalStorage;
Creating new folders
To create a new subfolder in the local folder, call the CreateFolderAsync method.
- String folderName =”csharp” ;
- IFolder folder = FileSystem.Current.LocalStorage;
- folder = await folder.CreateFolderAsync(folderName, CreationCollisionOption.ReplaceExisting);
Create New file
To create a new file in the local folder, call the CreateFileAsync method.
- String filename=”username.txt”;
- IFolder folder = FileSystem.Current.LocalStorage;
- 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.
- public async static Task<bool> IsFolderExistAsync(this string folderName, IFolder rootFolder = null)
- {
-
- IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;
- ExistenceCheckResult folderexist = await folder.CheckExistsAsync(folderName);
-
- if (folderexist == ExistenceCheckResult.FolderExists)
- {
- return true;
-
- }
- return false;
- }
Check File Already Exists
We can check for an existing file in a particular folder, as shown below.
- public async static Task<bool> IsFileExistAsync(this string fileName, IFolder rootFolder = null)
- {
-
- IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;
- ExistenceCheckResult folderexist = await folder.CheckExistsAsync(fileName);
-
- if (folderexist == ExistenceCheckResult.FileExists)
- {
- return true;
-
- }
- return false;
- }
Delete File
We can use the DeleteAsync method to delete the file.
- public async static Task<bool> DeleteFile(this string fileName, IFolder rootFolder = null)
- {
- IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;
- bool exist = await fileName.IsFileExistAsync(folder);
- if (exist == true)
- {
- IFile file = await folder.GetFileAsync(fileName);
- await file.DeleteAsync();
- return true;
- }
- return false;
- }
Write File
If you want to write any extension file document, just use the WriteAllTextAsync method for write.
- public async static Task<bool> WriteTextAllAsync(this string filename, string content = "", IFolder rootFolder = null)
- {
- IFile file = await filename.CreateFile(rootFolder);
- await file.WriteAllTextAsync(content);
- return true;
- }
Read File
If you want to read any extension file document, just use the ReadAllTextAsync method for write.
- public async static Task<string> ReadAllTextAsync(this string fileName, IFolder rootFolder = null)
- {
- string content = "";
- IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;
- bool exist = await fileName.IsFileExistAsync(folder);
- if (exist == true)
- {
- IFile file = await folder.GetFileAsync(fileName);
- content = await file.ReadAllTextAsync();
- }
- return content;
- }
Save Image
We can save the image, using PCLStorage, as shown below.
- public async static Task SaveImage(this byte[] image,String fileName, IFolder rootFolder = null)
- {
-
- IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;
-
-
- IFile file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
-
-
- using (System.IO.Stream stream = await file.OpenAsync(FileAccess.ReadAndWrite))
- {
- stream.Write(image, 0, image.Length);
- }
- }
Get Image
We can load an image, using PCLStorage, as shown below.
- public async static Task<byte[]> LoadImage(this byte[] image, String fileName, IFolder rootFolder = null)
- {
-
- IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;
-
-
- IFile file = await folder.GetFileAsync(fileName);
-
- using (System.IO.Stream stream = await file.OpenAsync(FileAccess.ReadAndWrite))
- {
- long length = stream.Length;
- byte[] streamBuffer = new byte[length];
- stream.Read(streamBuffer, 0, (int)length);
- return streamBuffer;
- }
-
- }
PCL Helper Class
I have created a very simple PCLHelper class. You can refer to it and reuse it in your project.
- using PCLStorage;
- using System;
- using System.Threading.Tasks;
-
- namespace DevEnvExe_LocalStorage
- {
- public static class PCLHelper
- {
-
- public async static Task<bool> IsFileExistAsync(this string fileName, IFolder rootFolder = null)
- {
-
- IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;
- ExistenceCheckResult folderexist = await folder.CheckExistsAsync(fileName);
-
- if (folderexist == ExistenceCheckResult.FileExists)
- {
- return true;
-
- }
- return false;
- }
-
- public async static Task<bool> IsFolderExistAsync(this string folderName, IFolder rootFolder = null)
- {
-
- IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;
- ExistenceCheckResult folderexist = await folder.CheckExistsAsync(folderName);
-
- if (folderexist == ExistenceCheckResult.FolderExists)
- {
- return true;
-
- }
- return false;
- }
-
- public async static Task<IFolder> CreateFolder(this string folderName, IFolder rootFolder = null)
- {
- IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;
- folder = await folder.CreateFolderAsync(folderName, CreationCollisionOption.ReplaceExisting);
- return folder;
- }
-
- public async static Task<IFile> CreateFile(this string filename, IFolder rootFolder = null)
- {
- IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;
- IFile file = await folder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
- return file;
- }
- public async static Task<bool> WriteTextAllAsync(this string filename, string content = "", IFolder rootFolder = null)
- {
- IFile file = await filename.CreateFile(rootFolder);
- await file.WriteAllTextAsync(content);
- return true;
- }
-
- public async static Task<string> ReadAllTextAsync(this string fileName, IFolder rootFolder = null)
- {
- string content = "";
- IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;
- bool exist = await fileName.IsFileExistAsync(folder);
- if (exist == true)
- {
- IFile file = await folder.GetFileAsync(fileName);
- content = await file.ReadAllTextAsync();
- }
- return content;
- }
- public async static Task<bool> DeleteFile(this string fileName, IFolder rootFolder = null)
- {
- IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;
- bool exist = await fileName.IsFileExistAsync(folder);
- if (exist == true)
- {
- IFile file = await folder.GetFileAsync(fileName);
- await file.DeleteAsync();
- return true;
- }
- return false;
- }
- public async static Task SaveImage(this byte[] image,String fileName, IFolder rootFolder = null)
- {
-
- IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;
-
-
- IFile file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
-
-
- using (System.IO.Stream stream = await file.OpenAsync(FileAccess.ReadAndWrite))
- {
- stream.Write(image, 0, image.Length);
- }
- }
-
- public async static Task<byte[]> LoadImage(this byte[] image, String fileName, IFolder rootFolder = null)
- {
-
- IFolder folder = rootFolder ?? FileSystem.Current.LocalStorage;
-
-
- IFile file = await folder.GetFileAsync(fileName);
-
- using (System.IO.Stream stream = await file.OpenAsync(FileAccess.ReadAndWrite))
- {
- long length = stream.Length;
- byte[] streamBuffer = new byte[length];
- stream.Read(streamBuffer, 0, (int)length);
- return streamBuffer;
- }
-
- }
- }
- }
I believe this will be helpful for all Xamarin developers. If you have any questions, please post them in the comment box.