Windows Store (WinRT/Metro) - File Helper Methods

Posted by Blake on 8/31/2012
)

Here are some file helper methods that I’ve put together to speed along dealing with reading and writing basic text and information to the file system in a Metro app. The security model is much tighter in Metro apps which brings more work when dealing with the file system. My initial pass at this was meant to cover reading and writing strings and byte arrays. Metro apps can get to local storage without additional permissions (that is isolated when running Metro) and can get to certain known folders like My Documents, Pictures, etc. when specifically requesting access via the manifest (it’s a little cumbersome in my opinion).

Since I will deal a lot with local storage, most of my methods are centered around those though I have overloads to deal with a StorageFile that you can initialize that goes into one of the other KnownFolders. These are designed to be similar to the Visual Basic “My.Computer.FileSystem.WriteAllText” and “My.Computer.FileSystem.WriteAllBytes” (and the read equivalents) methods.

This is my first pass, these will likely change as I use these in apps, fix bugs and find better ways to handle files.

VB.Net


Imports Windows.Storage
Namespace IO

    ''' <summary>
    ''' Methods to assist working with files.
    ''' </summary>
    ''' <remarks></remarks>
    Public Class FileHelpers
        '*********************************************************************************************************************
        '
        '             Class:  FileHelpers
        '      Initial Date:  08/29/2012
        '      Last Updated:  08/31/2012
        '     File Revision:  0
        '     Programmer(s):  Blake Pell (blakepell@hotmail.com, http://www.blakepell.com)
        '
        '*********************************************************************************************************************

        ''' <summary>
        ''' A safe storage folder, available to the WinRT application that doesn't need additional manifest permissions
        ''' </summary>
        ''' <remarks></remarks>
        Enum SafeStorageFolder
            Local
            Roaming
            Temp
        End Enum

        ''' <summary>
        ''' Writes all of the text to a specified file in the Local storage.
        ''' </summary>
        ''' <param name="text">The text to write.</param>
        ''' <param name="append">Whether or not to append the data or overwrite what is in the file.</param>
        ''' <param name="fileName">The name of the file to write the data to.</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Async Function WriteAllText(text As String, append As Boolean, fileName As String) As Task
            Await WriteAllText(text, append, fileName, SafeStorageFolder.Local)
        End Function

        ''' <summary>
        ''' Writes all of the text to the specified file in one of the specified safe storage folders.
        ''' </summary>
        ''' <param name="text">The text to write.</param>
        ''' <param name="append">Whether or not to append the data or overwrite what is in the file.</param>
        ''' <param name="fileName">The name of the file to write the data to.</param>
        ''' <param name="safeFolder">The safe storage folder that should be written to.  These folders are isolated for the application to use
        ''' and do not require additional manifest permissions.</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Async Function WriteAllText(text As String, append As Boolean, fileName As String, safeFolder As SafeStorageFolder) As Task
            Dim folder As Windows.Storage.StorageFolder
            Select Case safeFolder
                Case SafeStorageFolder.Local
                    folder = Windows.Storage.ApplicationData.Current.LocalFolder
                Case SafeStorageFolder.Roaming
                    folder = Windows.Storage.ApplicationData.Current.RoamingFolder
                Case SafeStorageFolder.Temp
                    folder = Windows.Storage.ApplicationData.Current.TemporaryFolder
                Case Else
                    folder = Windows.Storage.ApplicationData.Current.LocalFolder
            End Select
            Dim sf As StorageFile
            If append = True Then
                sf = Await folder.CreateFileAsync(fileName, Windows.Storage.CreationCollisionOption.OpenIfExists)
            Else
                sf = Await folder.CreateFileAsync(fileName, Windows.Storage.CreationCollisionOption.ReplaceExisting)
            End If
            ' WriteTextAsync will always overwrite the file even if the existing file has been opened.  We'll use
            ' AppendTextAsync here, the above CreateFileAsync will handle whether the file has been truncated or not.
            Await FileIO.AppendTextAsync(sf, text)
        End Function

        ''' <summary>
        ''' Writes all of the text to the specified file in a StorageFolder that has been initialized by the caller.
        ''' </summary>
        ''' <param name="text">The text to write.</param>
        ''' <param name="append">Whether or not to append the data or overwrite what is in the file.</param>
        ''' <param name="fileName">The name of the file to write the data to.</param>
        ''' <param name="folder">The StorageFolder that has been initialized by the caller.  If this is a KnownFolder such as to the users Documents then 
        ''' proper manifest settings will need to be in place for this to execute.</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Async Function WriteAllText(text As String, append As Boolean, fileName As String, folder As StorageFolder) As Task
            Dim sf As StorageFile
            If append = True Then
                sf = Await folder.CreateFileAsync(fileName, Windows.Storage.CreationCollisionOption.OpenIfExists)
            Else
                sf = Await folder.CreateFileAsync(fileName, Windows.Storage.CreationCollisionOption.ReplaceExisting)
            End If
            ' WriteTextAsync will always overwrite the file even if the existing file has been opened.  We'll use
            ' AppendTextAsync here, the above CreateFileAsync will handle whether the file has been truncated or not.
            Await FileIO.AppendTextAsync(sf, text)
        End Function

        ''' <summary>
        ''' Writes all of the text to the specified file in the local storage folder.
        ''' </summary>
        ''' <param name="b">The byte array to write.</param>
        ''' <param name="fileName">The name of the file to write the data to.</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Async Function WriteAllBytes(b() As Byte, fileName As String) As Task
            Await WriteAllBytes(b, fileName, SafeStorageFolder.Local)
        End Function

        ''' <summary>
        ''' Writes all of the text to the specified file in one of the specified safe storage folders.
        ''' </summary>
        ''' <param name="b">The byte array to write.</param>
        ''' <param name="fileName">The name of the file to write the data to.</param>
        ''' <param name="safeFolder">The safe storage folder that should be written to.  These folders are isolated for the application to use
        ''' and do not require additional manifest permissions.</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Async Function WriteAllBytes(b() As Byte, fileName As String, safeFolder As SafeStorageFolder) As Task
            Dim folder As Windows.Storage.StorageFolder
            Select Case safeFolder
                Case SafeStorageFolder.Local
                    folder = Windows.Storage.ApplicationData.Current.LocalFolder
                Case SafeStorageFolder.Roaming
                    folder = Windows.Storage.ApplicationData.Current.RoamingFolder
                Case SafeStorageFolder.Temp
                    folder = Windows.Storage.ApplicationData.Current.TemporaryFolder
                Case Else
                    folder = Windows.Storage.ApplicationData.Current.LocalFolder
            End Select
            Dim sf As StorageFile
            sf = Await folder.CreateFileAsync(fileName, Windows.Storage.CreationCollisionOption.OpenIfExists)
            ' WriteTextAsync will always overwrite the file even if the existing file has been opened.  We'll use
            ' AppendTextAsync here, the above CreateFileAsync will handle whether the file has been truncated or not.
            Await FileIO.WriteBytesAsync(sf, b)
        End Function

        ''' <summary>
        ''' Writes all of the text to the specified file in one of the specified safe storage folders.
        ''' </summary>
        ''' <param name="b">The byte array to write.</param>
        ''' <param name="fileName">The name of the file to write the data to.</param>
        ''' <param name="folder">The StorageFolder that has been initialized by the caller.  If this is a KnownFolder such as to the users Documents then 
        ''' proper manifest settings will need to be in place for this to execute.</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Async Function WriteAllBytes(b() As Byte, fileName As String, folder As StorageFolder) As Task
            Dim sf As StorageFile
            sf = Await folder.CreateFileAsync(fileName, Windows.Storage.CreationCollisionOption.OpenIfExists)
            ' WriteTextAsync will always overwrite the file even if the existing file has been opened.  We'll use
            ' AppendTextAsync here, the above CreateFileAsync will handle whether the file has been truncated or not.
            Await FileIO.WriteBytesAsync(sf, b)
        End Function

        ''' <summary>
        ''' Writes all of the text to a specified file in the Local storage.
        ''' </summary>
        ''' <param name="text">The text to write.</param>
        ''' <param name="append">Whether or not to append the data or overwrite what is in the file.</param>
        ''' <param name="fileName">The name of the file to write the data to.</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Async Function WriteAllLines(text As IEnumerable(Of String), append As Boolean, fileName As String) As Task
            Await WriteAllLines(text, append, fileName, SafeStorageFolder.Local)
        End Function

        ''' <summary>
        ''' Writes all of the text to the specified file in one of the specified safe storage folders.
        ''' </summary>
        ''' <param name="text">The text to write.</param>
        ''' <param name="append">Whether or not to append the data or overwrite what is in the file.</param>
        ''' <param name="fileName">The name of the file to write the data to.</param>
        ''' <param name="safeFolder">The safe storage folder that should be written to.  These folders are isolated for the application to use
        ''' and do not require additional manifest permissions.</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Async Function WriteAllLines(text As IEnumerable(Of String), append As Boolean, fileName As String, safeFolder As SafeStorageFolder) As Task
            Dim folder As Windows.Storage.StorageFolder
            Select Case safeFolder
                Case SafeStorageFolder.Local
                    folder = Windows.Storage.ApplicationData.Current.LocalFolder
                Case SafeStorageFolder.Roaming
                    folder = Windows.Storage.ApplicationData.Current.RoamingFolder
                Case SafeStorageFolder.Temp
                    folder = Windows.Storage.ApplicationData.Current.TemporaryFolder
                Case Else
                    folder = Windows.Storage.ApplicationData.Current.LocalFolder
            End Select
            Dim sf As StorageFile
            If append = True Then
                sf = Await folder.CreateFileAsync(fileName, Windows.Storage.CreationCollisionOption.OpenIfExists)
            Else
                sf = Await folder.CreateFileAsync(fileName, Windows.Storage.CreationCollisionOption.ReplaceExisting)
            End If
            ' WriteTextAsync will always overwrite the file even if the existing file has been opened.  We'll use
            ' AppendTextAsync here, the above CreateFileAsync will handle whether the file has been truncated or not.
            Await FileIO.AppendLinesAsync(sf, text)
        End Function

        ''' <summary>
        ''' Writes all of the text to the specified file in a StorageFolder that has been initialized by the caller.
        ''' </summary>
        ''' <param name="text">The text to write.</param>
        ''' <param name="append">Whether or not to append the data or overwrite what is in the file.</param>
        ''' <param name="fileName">The name of the file to write the data to.</param>
        ''' <param name="folder">The StorageFolder that has been initialized by the caller.  If this is a KnownFolder such as to the users Documents then 
        ''' proper manifest settings will need to be in place for this to execute.</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Async Function WriteAllLines(text As IEnumerable(Of String), append As Boolean, fileName As String, folder As StorageFolder) As Task
            Dim sf As StorageFile
            If append = True Then
                sf = Await folder.CreateFileAsync(fileName, Windows.Storage.CreationCollisionOption.OpenIfExists)
            Else
                sf = Await folder.CreateFileAsync(fileName, Windows.Storage.CreationCollisionOption.ReplaceExisting)
            End If
            ' WriteTextAsync will always overwrite the file even if the existing file has been opened.  We'll use
            ' AppendTextAsync here, the above CreateFileAsync will handle whether the file has been truncated or not.
            Await FileIO.AppendLinesAsync(sf, text)
        End Function

        ''' <summary>
        ''' Reads all of the text in as a string from the specified file in the local storage folder.
        ''' </summary>
        ''' <param name="fileName">The name of the file to read all of the text from.</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Async Function ReadAllText(fileName As String) As Task(Of String)
            Return Await ReadAllText(fileName, SafeStorageFolder.Local)
        End Function

        ''' <summary>
        ''' Reads all of the text in as a string from the specified file in one of the safe storage folders.
        ''' </summary>
        ''' <param name="fileName">The name of the file to read all of the text from.</param>
        ''' <param name="safeFolder">The safe storage folder that should be written to.  These folders are isolated for the application to use
        ''' and do not require additional manifest permissions.</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Async Function ReadAllText(fileName As String, safeFolder As SafeStorageFolder) As Task(Of String)
            Dim folder As Windows.Storage.StorageFolder
            Select Case safeFolder
                Case SafeStorageFolder.Local
                    folder = Windows.Storage.ApplicationData.Current.LocalFolder
                Case SafeStorageFolder.Roaming
                    folder = Windows.Storage.ApplicationData.Current.RoamingFolder
                Case SafeStorageFolder.Temp
                    folder = Windows.Storage.ApplicationData.Current.TemporaryFolder
                Case Else
                    folder = Windows.Storage.ApplicationData.Current.LocalFolder
            End Select
            Dim sf As StorageFile
            sf = Await folder.GetFileAsync(fileName)
            Return Await FileIO.ReadTextAsync(sf)
        End Function

        ''' <summary>
        ''' Reads all of the text in as a string from the specified file in one of the safe storage folders.
        ''' </summary>
        ''' <param name="fileName">The name of the file to open and read.</param>
        ''' <param name="folder">The StorageFolder that has been initialized by the caller.  If this is a KnownFolder such as to the users Documents then 
        ''' proper manifest settings will need to be in place for this to execute.</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Async Function ReadAllText(fileName As String, folder As StorageFolder) As Task(Of String)
            Dim sf As StorageFile
            sf = Await folder.GetFileAsync(fileName)
            Return Await FileIO.ReadTextAsync(sf)
        End Function

        ''' <summary>
        ''' Deletes the specified file from the safe folder.
        ''' </summary>
        ''' <param name="fileName">The name of the file to delete.</param>
        ''' <param name="safeFolder">The safe storage folder that should be written to.  These folders are isolated for the application to use
        ''' and do not require additional manifest permissions.</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Async Function DeleteFile(fileName As String, safeFolder As SafeStorageFolder) As Task
            Dim folder As Windows.Storage.StorageFolder
            Select Case safeFolder
                Case SafeStorageFolder.Local
                    folder = Windows.Storage.ApplicationData.Current.LocalFolder
                Case SafeStorageFolder.Roaming
                    folder = Windows.Storage.ApplicationData.Current.RoamingFolder
                Case SafeStorageFolder.Temp
                    folder = Windows.Storage.ApplicationData.Current.TemporaryFolder
                Case Else
                    folder = Windows.Storage.ApplicationData.Current.LocalFolder
            End Select
            Await folder.DeleteAsync(StorageDeleteOption.PermanentDelete)
        End Function

        ''' <summary>
        ''' Deletes the specified file from the safe folder.
        ''' </summary>
        ''' <param name="fileName">The name of the file to delete.</param>
        ''' <param name="newName">The name that you want the file to be renamed to.</param>
        ''' <param name="safeFolder">The safe storage folder that should be written to.  These folders are isolated for the application to use
        ''' and do not require additional manifest permissions.</param>
        ''' <param name="overwrite">Whether or not the destination file should be overwritten if a file of the same name exists.  If this value
        ''' is false and the filename already exists an exception will be generated.</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Async Function RenameFile(fileName As String, newName As String, safeFolder As SafeStorageFolder, overwrite As Boolean) As Task
            Dim folder As Windows.Storage.StorageFolder
            Select Case safeFolder
                Case SafeStorageFolder.Local
                    folder = Windows.Storage.ApplicationData.Current.LocalFolder
                Case SafeStorageFolder.Roaming
                    folder = Windows.Storage.ApplicationData.Current.RoamingFolder
                Case SafeStorageFolder.Temp
                    folder = Windows.Storage.ApplicationData.Current.TemporaryFolder
                Case Else
                    folder = Windows.Storage.ApplicationData.Current.LocalFolder
            End Select
            If overwrite = True Then
                Await folder.RenameAsync(newName, NameCollisionOption.ReplaceExisting)
            Else
                Await folder.RenameAsync(newName, NameCollisionOption.FailIfExists)
            End If
        End Function

    End Class

End Namespace