User Tools

Site Tools


notes:uwp:appdata

Files and Streams in UWP

The ApplicationData class represents the Application Local Storage area on the hard drive that is private to an app. It contains folders where the app can store data. These folders (local, roaming and temporary) are created when the app is installed.

Obtain access to the local, roaming, and temporary folders:

using Windows.Storage;
...
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
StorageFolder roamingFolder = ApplicationData.Current.RoamingFolder;
StorageFolder temporaryFolder = ApplicationData.Current.TemporaryFolder;

Obtain the path to the local folder:

string path = ApplicationData.Current.LocalFolder.Path;

StorageFile & StorageFolder

You can manage files using the methods of the StorageFile and StorageFolder classes.

var localFolder = ApplicationData.Current.LocalFolder;
 
// Create a new file or open an existing one.
StorageFile file = await localFolder.CreateFileAsync("data.txt", CreationCollisionOption.OpenIfExists);
 
// Create a new file or override an existing one.
StorageFile file = await localFolder.CreateFileAsync("data.txt", CreationCollisionOption.ReplaceExisting);
 
// Create a new file with a unique name.
StorageFile file = await localFolder.CreateFileAsync("data.txt", CreationCollisionOption.GenerateUniqueName); 
 
// Obtain a file by its name.
StorageFile file = await localFolder.GetFileAsync("data.txt");
 
// Obtain a file by its full path.
string path = System.IO.Path.Combine(localFolder.Path, "data.txt");
StorageFile file = await StorageFile.GetFileFromPathAsync(path);
 
// Delete all package files.
await ApplicationData.Current.ClearAsync();
 
// Obtain all files located in a given folder.
IReadOnlyList<StorageFile> files = await localFolder.GetFilesAsync()

The StorageFile class provides the GetFileFromApplicationUriAsync method as well as the GetFileFromPathAsync method to load files using URIs.

FileIO, FolderIO, PathIO

Static methods FileIO, FolderIO, and PathIO are not suitable for working with large files because they read the whole file into memory all at once.

Append a string to a text file. It's useful for a quick logging mechanism:

string str = "Test";
StorageFile file = 
   await ApplicationData.Current.LocalFolder.CreateFileAsync("test.txt", CreationCollisionOption.OpenIfExists);
await FileIO.AppendTextAsync(file, str, Windows.Storage.Streams.UnicodeEncoding.Utf8);

Read from a text file:

// Read an entire file as a single string.
string data = await FileIO.ReadTextAsync(file);
 
// Read an entire file as a list of strings. Each string should be separated by a NewLine character.
IList<string> list = await FileIO.ReadLinesAsync(file);

Write data to a binary file:

using Windows.Storage;
using Windows.Storage.Streams;
...
// Create a new file.
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
StorageFile file = await localFolder.CreateFileAsync("data.bin", CreationCollisionOption.ReplaceExisting);
 
// Write to the binary file.
using (DataWriter writer = new DataWriter())
{
    // Write binary data to DataWriter.
    // DataWriter stores data in an internal IBuffer.
    writer.WriteBytes(new byte[] { 120, 34, 18, 234, 68 });
 
    // Write data from the internal IBuffer to the binary file.
    await FileIO.WriteBufferAsync(file, writer.DetachBuffer());
}

Prepare binary data in a separate method (GetBuffer) and write it to a file:

using Windows.Storage;
using Windows.Storage.Streams;
...
private async void WriteToBinaryFile()
{
    // Create a new file.
    StorageFolder localFolder = ApplicationData.Current.LocalFolder;
    StorageFile file = await localFolder.CreateFileAsync("data.bin", CreationCollisionOption.ReplaceExisting);
 
    await FileIO.WriteBufferAsync(file, GetBuffer());
}
 
// A helper method to prepare a buffer with binary data.
private IBuffer GetBuffer()
{
    IBuffer buffer;
 
    using (DataWriter writer = new DataWriter())
    {
        writer.WriteBytes(new byte[] { 120, 34, 18, 234, 68 });
        buffer = writer.DetachBuffer();
    }
 
    return buffer;
}

Read data from a binary file:

using Windows.Storage;
using Windows.Storage.Streams;
...
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
StorageFile file = await localFolder.GetFileAsync("data.bin");
 
IBuffer buffer = await FileIO.ReadBufferAsync(file);
using (DataReader reader = DataReader.FromBuffer(buffer))
{
    // Read data from DataReader.
    byte[] data = new byte[buffer.Length];
    reader.ReadBytes(data);
 
    // Display data in the Debug window.
    foreach (byte b in data)
        Debug.WriteLine(b);
}

Read data from a binary file using a .NET class System.IO.BinaryReader and the extension method AsStreamForRead:

using System.IO;
using Windows.Storage;
using Windows.Storage.Streams;
...
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
StorageFile file = await localFolder.GetFileAsync("data.bin");
 
// The OpenReadAsync method opens a random-access stream over the current file for reading file contents.
// When the method completes, it returns the random-access stream of type IRandomAccessStreamWithContentType.
IRandomAccessStreamWithContentType stream = await file.OpenReadAsync();
stream.Seek(0);
BinaryReader reader = new BinaryReader(stream.AsStreamForRead());
byte[] buffer = new byte[stream.Size];
reader.Read(buffer, 0, buffer.Length);

Methods of a static PathIO class are identical to those of the FileIO class except that the methods accept an absolute path string instead of an IStorageFile.

// Write the lines.
StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync("data.txt");  
String[] output = new[] { "Line 1", "Line 2" }; 
await PathIO.WriteLinesAsync(file.Path, output); 
 
// Read the lines from the file (decoded with UTF-8): 
IList<String> input = await PathIO.ReadLinesAsync(file.Path);
// Read data from a location provided as an URI.
var buffer = await PathIO.ReadBufferAsync(uri);

FileIO methods:

  • AppendLinesAsync
  • AppendTextAsync
  • ReadLinesAsync
  • ReadTextAsync
  • ReadBufferAsync
  • WriteLinesAsync
  • WriteTextAsync
  • WriteBufferAsync
  • WriteBytesAsync

A few traits of IBuffer:

  • Represents an array of bytes in system memory.
  • Provides a convenient way to transfer bytes from one stream to another.
  • It is possible to convert IBuffer to an array of bytes.
  • Defines two properties: Capacity and Length.
  • The ReadAsync method defined by the IInputStream interface reads from a stream into an IBuffer.
  • The WriteAsync method defined by the IOutputStream interface writes from the IBuffer into the stream.

DataReader and DataWriter

The Windows.Storage.Streams.DataWriter and Windows.Storage.Streams.DataReader classes are equivalent of the .NET System.IO.BinaryWriter and System.IO.BinaryReader classes for storing and retrieving primitive data types from a stream.

Example: Write and read from a stream:

using Windows.Storage;
using Windows.Storage.Streams;
...
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
StorageFile file = await localFolder.CreateFileAsync("data.dat", CreationCollisionOption.ReplaceExisting);
 
using (var writer = new DataWriter(await file.OpenAsync(FileAccessMode.ReadWrite)))
{
    writer.WriteBytes(new Byte[] { 8, 6, 4 });
 
    const string str = "Testing";
 
    // MeasureString returns how many bytes a string requires when encoded via UnicodeEncoding.
    uint len = writer.MeasureString(str); // measure the string taking into account encoding (why 7?)
    writer.WriteUInt32(len); // store the string length
    writer.WriteString(str); // store the string
 
    uint bytesStored = await writer.StoreAsync(); // commit buffer to the stream
    Debug.WriteLine($"Bytes stored: {bytesStored}"); // 14
} // close DataWriter and the underlying stream
 
 
// LoadAsync reads count bytes from stream appending them to the buffer.
using (var reader = new DataReader(await file.OpenAsync(FileAccessMode.Read)))
{
    byte[] bytes = new byte[3];
    uint bytesRead = await reader.LoadAsync((uint)bytes.Length);
    reader.ReadBytes(bytes);
 
    // Get the length of the string.
    bytesRead = await reader.LoadAsync(sizeof(uint));
    var len = reader.ReadUInt32();
 
    // Read the string.
    bytesRead = await reader.LoadAsync(len);
    string str = reader.ReadString(len);
    Debug.WriteLine($"String: {str}");
} // close DataReader and the underlying stream

Links

Application URI

You can access files using the StorageFile.GetFileFromApplicationUriAsync method and providing a URI with the ms-appdata:/// prefix.

Folder URI Prefix
LocalFolder ms-appdata:///local
RoamingFolder ms-appdata:///roaming
TemporaryFolder ms-appdata:///temp
InstallFolder ms-appx:///
// Retrieve a file test.txt located in ApplicationData.Current.LocalFolder.
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appdata:///local/test.txt"));

ms-appx-web points to resources stored in the app's package for use in web scenarios; it accesses the same files as ms-appx but in the web compartment.

Copying Files

Copy a file from the installation folder to the local folder:

// Method #1
 
// sourcePath is the path of a file in the installation folder. It must be prefixed with ms-appx:/// 
string sourcePath = "ms-appx:///data.txt";
 
// destFilename is the desired name of the filename in the local folder.
string destFilename = "data.txt";
 
// Obtain a file from the installation folder.
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(sourcePath));
 
// Copy the file to the local folder.
await file.CopyAsync(Windows.Storage.ApplicationData.Current.LocalFolder, 
    destFilename, NameCollisionOption.ReplaceExisting);
// Method #2
using Windows.ApplicationModel;
using Windows.Storage;
...
StorageFile sourceFile = await Package.Current.InstalledLocation.GetFileAsync("Assets\\logo.png");
StorageFile destFile = 
  await ApplicationData.Current.LocalFolder.CreateFileAsync("copy.png", CreationCollisionOption.ReplaceExisting);
 
// Create a new file.
var buffer = await FileIO.ReadBufferAsync(sourceFile);
await FileIO.WriteBufferAsync(destFile, buffer);

Installed Location

Set a file's Build Action property to Content in order to access the file in the code.

Example: Access a file in the install directory (the package's directory):

using Windows.Storage;
...
// Method #1
StorageFolder folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
StorageFile file = await folder.GetFileAsync(@"Assets\Image.png");
 
// Method #2
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/image.png"));

Note that ms-appx:///Assets/image.png is equivalent to

"ms-appx://" + Windows.ApplicationModel.Package.Current.Id.Name + "/Assets/image.png"

Serialization

Example: An exmaple of XML serialization.

This program provides two buttons:

  • The [Save Books] button serializes a bunch of book objects (represented as a BookModel class) to individual XML files, one file for each book.
  • The [Load Books] button deserializes books from XML files to a collection.
<Page x:Class="TestApp.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
 
    <Grid>
        <StackPanel>
            <Button Content="Save Books" Margin="16" Click="SaveBooksButton_Click" />
            <Button Content="Load Books" Margin="16" Click="LoadBooksButton_Click" />
        </StackPanel>
    </Grid>
</Page>
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.Serialization;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.Storage.Search; // StorageFileQueryResult
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
 
namespace TestApp
{
    [DataContract(Name = "Book")]
    public class BookModel
    {
        [DataMember]
        public int Id { get; set; }
        [DataMember]
        public string Title { get; set; }
        [DataMember]
        public string Author { get; set; }
 
        public override string ToString()
        {
            return String.Format("Id = {0}, Title = {1}, Author = {2}", Id, Title, Author);
        }
    }
 
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }
 
        private async void SaveBooksButton_Click(object sender, RoutedEventArgs e)
        {
            await SaveBookAsync(new BookModel { Id = 1, Title = "Book1", Author = "Author1" }, "book1.xml");
            await SaveBookAsync(new BookModel { Id = 2, Title = "Book2", Author = "Author2" }, "book2.xml");
            await SaveBookAsync(new BookModel { Id = 3, Title = "Book3", Author = "Author3" }, "book3.xml");
        }
 
        private async void LoadBooksButton_Click(object sender, RoutedEventArgs e)
        {
            IEnumerable<BookModel> books = await GetBooksAsync();
            foreach (BookModel book in books)
                Debug.WriteLine(book.ToString());
        }
 
        public async Task SaveBookAsync(BookModel book, string filename)
        {
            var knownTypes = new Type[]
            {
                typeof(BookModel)
            };
 
            var ser = new DataContractSerializer(typeof(BookModel), knownTypes);
 
            // Create the data file.
            StorageFolder folder = ApplicationData.Current.LocalFolder;
            StorageFile file = await folder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
 
            using (MemoryStream ms = new MemoryStream())
            {
                // Fill the .NET memory stream with data.
                ser.WriteObject(ms, book);
 
                // Use the extension method OpenStreamForWriteAsync to obtain the .NET stream.
                using (Stream fs = await file.OpenStreamForWriteAsync())
                {
                    ms.Seek(0, SeekOrigin.Begin);
                    await ms.CopyToAsync(fs);
                    await fs.FlushAsync();
                }
            }
        }
 
        public async Task<IEnumerable<BookModel>> GetBooksAsync()
        {
            IList<BookModel> items = new List<BookModel>();
 
            StorageFolder folder = ApplicationData.Current.LocalFolder;
 
            StorageFileQueryResult result = folder.CreateFileQuery();
            var options = new QueryOptions();
            options.IndexerOption = IndexerOption.DoNotUseIndexer; // access the file system directly
            options.FolderDepth = FolderDepth.Shallow;
            options.FileTypeFilter.Add(".xml");
            result.ApplyNewQueryOptions(options);
 
            IReadOnlyList<StorageFile> files = await result.GetFilesAsync();
 
            foreach (StorageFile file in files)
            {
                using (Stream stream = await file.OpenStreamForReadAsync())
                {
                    var ser = new DataContractSerializer(typeof(BookModel));
                    object data = await Task<object>.Run(() => ser.ReadObject(stream));
                    items.Add(data as BookModel);
                }
            }
 
            return items;
        }
    }
}

KnownFolders

Known Folder Description
MusicLibrary Gets the Music library
PicturesLibrary Gets the Pictures library
VideosLibrary Gets the Videos library
HomeGroup Gets the HomeGroup folder. The app must be configured with the Music Library, Pictures Library, or Videos Library capability in the package manifest.
RemovableDevices Gets the Removable Devices section in My Computer. Includes devices such as USB flash drives and external portable drives. The app must be configured with the Removable Storage capability.
MediaServerDevices Gets the Media Server Devices (Digital Living Network Alliance [DLNA]) folder. The app must be configured with the Music Library, Pictures Library, or Videos Library capability in the package manifest.
DocumentsLibrary The use of the DocumentsLibrary capability is discouraged in Win 8.1 and Win 10

Example: Display a flat list of files located in the PicturesLibrary folder and its subfolders.

You can use the APIs in the Windows.Storage namespace to retrieve folder and file data. However, the various GetFilesAsync, GetFoldersAsync, and GetItemsAsync methods do not return values that are suitable for binding to list controls. Instead, you must bind to the return values of the GetVirtualizedFilesVector, GetVirtualizedFoldersVector, and GetVirtualizedItemsVector methods of the FileInformationFactory class.

<ListView x:Name="PicturesListView" Height="300" DisplayMemberPath="DisplayName" />
var library = Windows.Storage.KnownFolders.PicturesLibrary;
var queryOptions = new Windows.Storage.Search.QueryOptions();
queryOptions.FolderDepth = Windows.Storage.Search.FolderDepth.Deep;
queryOptions.IndexerOption = Windows.Storage.Search.IndexerOption.UseIndexerWhenAvailable;
 
var query = library.CreateFileQueryWithOptions(queryOptions);
 
var info = new Windows.Storage.BulkAccess.FileInformationFactory(
    query,
    Windows.Storage.FileProperties.ThumbnailMode.PicturesView,
    190,
    Windows.Storage.FileProperties.ThumbnailOptions.UseCurrentScale,
    false);
 
var dataSource = info.GetVirtualizedFilesVector();
 
PicturesListView.ItemsSource = dataSource;

Example: Access items in PicturesLibrary:

StorageFolder picturesFolder = KnownFolders.PicturesLibrary;
IReadOnlyList<IStorageItem> items = await picturesFolder.GetItemsAsync();
 
foreach (IStorageItem item in items)
{
    if (item is StorageFolder)
        Debug.WriteLine("Folder: " + item.Name);
    else if (item is StorageFile)
        Debug.WriteLine("File: " + item.Name);
    else
        Debug.WriteLine("Other: " + item.Name);
}

Example: Group pictures by their creation month using the CreateFolderQuery method. The CreateFolderQuery method filters all files in the current folder as well as in all subfolders. That's why some files are listed twice when multiple copies are located in different subfolders.

using Windows.Storage.Search;
...
StorageFolder library = KnownFolders.PicturesLibrary;
 
if (library.IsCommonFolderQuerySupported(CommonFolderQuery.GroupByMonth))
{
    StorageFolderQueryResult result = library.CreateFolderQuery(CommonFolderQuery.GroupByMonth);
    IReadOnlyList<IStorageItem> folders = await result.GetFoldersAsync();
    foreach (StorageFolder folder in folders)
    {
        IReadOnlyList<StorageFile> files = await folder.GetFilesAsync();
 
        // Show the month and the number of files in this group.
        Debug.WriteLine("{0} ({1})", folder.Name, files.Count);
 
        // Show the filenames.
        foreach (StorageFile file in files)
            Debug.WriteLine("    {0}", file.Name);
    }
}

Output:

November 2014 (3)
    list.txt
    test.txt
    winrt_06.png
October 2014 (1)
    winrt_05.png
September 2014 (3)
    Logo24.psd
    Logo30.psd
    Logo42.psd
February 2013 (1)
    image1.jpg
January 2013 (4)
    pic1.jpg
    pic1.jpg
    pic2.jpg
    pic2.jpg
July 2006 (2)
    Lighthouse.jpg
    Lighthouse.jpg

Indexed Folder

Windows Search does not index the contents of your package's folders (more details here). However, if you create a folder called “Indexed” in your package's local folder, Windows Search will index the contents of this folder.

Example: Create the “Indexed” folder, add two text files to it, and then perform a query against the folder:

// Create the "Indexed" subdirectory in the Local package folder. 
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
StorageFolder indexed = await localFolder.CreateFolderAsync("Indexed");
 
// Create two text files in the "Indexed" subdirectory: 
await FileIO.WriteTextAsync(await indexed.CreateFileAsync("data1.txt"), "aa bb cc");
await FileIO.WriteTextAsync(await indexed.CreateFileAsync("data2.txt"), "aa dd ee");
 
// Create a query that looks for .txt files containing "dd" 
var query = new QueryOptions(CommonFileQuery.DefaultQuery, new[] { ".txt" })
{
    ApplicationSearchFilter = "dd",
    IndexerOption = IndexerOption.OnlyUseIndexer, // use indexed files only 
    FolderDepth = FolderDepth.Deep // search subdirectories too 
};
 
StorageFileQueryResult results = localFolder.CreateFileQueryWithOptions(query);
 
// Perform the query and get the results.
IReadOnlyList<StorageFile> result = await results.GetFilesAsync(); 
 
// 'result' is a list containing a single StorageFile - data2.txt

Semaphore

Example: Write a piece of text to a file in a multithreaded environemnt:

private SemaphoreSlim mutex = new SemaphoreSlim(1);
public async void WriteLine(string str)
{
    await mutex.WaitAsync();
    try
    {
        // Create a new file or return an existing file if it already exists.
        var folder = ApplicationData.Current.LocalFolder;
        StorageFile file = await folder.CreateFileAsync("data.txt", CreationCollisionOption.OpenIfExists);
 
        await FileIO.AppendTextAsync(file, str);
    }
    finally
    {
        mutex.Release();
    }
}

More info on that here.

Storage Object Model

  • IStorageItem exposes members that operate on both files and folders:
public interface IStorageItem
{
    FileAttributes Attributes { get; }  // FileAttributes.ReadOnly, FileAttributes.Archive, etc.
    DateTimeOffset DateCreated { get; } // 7/26/2016 10:50:00 AM -06:00
    System.String Name { get; }         // picture.jpg
    System.String Path { get; }         // C:\Pictures\picture.jpg
 
    IAsyncAction DeleteAsync();
    IAsyncAction DeleteAsync(StorageDeleteOption option);
    IAsyncOperation<BasicProperties> GetBasicPropertiesAsync();
    bool IsOfType(StorageItemTypes type);
    IAsyncAction RenameAsync(string desiredName);
    IAsyncAction RenameAsync(string desiredName, NameCollisionOption option);
}
  • IStorageFolder inherits from IStorageItem and adds members that are specific to folders:
public interface IStorageFolder : IStorageItem
{
    IAsyncOperation<StorageFile> CreateFileAsync(string desiredName);
    IAsyncOperation<StorageFile> CreateFileAsync(string desiredName, CreationCollisionOption options);
    IAsyncOperation<StorageFolder> CreateFolderAsync(string desiredName);
    IAsyncOperation<StorageFolder> CreateFolderAsync(string desiredName, CreationCollisionOption options);
    IAsyncOperation<StorageFile> GetFileAsync(string name);
    IAsyncOperation<IReadOnlyList<StorageFile>> GetFilesAsync();
    IAsyncOperation<StorageFolder> GetFolderAsync(string name);
    IAsyncOperation<IReadOnlyList<StorageFolder>> GetFoldersAsync();
    IAsyncOperation<IStorageItem> GetItemAsync(string name);
    IAsyncOperation<IReadOnlyList<IStorageItem>> GetItemsAsync();
}
  • IStorageFile also inherits from IStorageItem and adds members that are specific to files:
public interface IStorageFile : IStorageItem, IRandomAccessStreamReference, IInputStreamReference
{
    string ContentType { get; } // .image/jpeg
    string FileType { get; }    // .jpg
 
    IAsyncAction CopyAndReplaceAsync(IStorageFile fileToReplace);
    IAsyncOperation<StorageFile> CopyAsync(IStorageFolder destinationFolder);
    IAsyncOperation<StorageFile> CopyAsync(IStorageFolder destinationFolder, string desiredNewName);
    IAsyncOperation<StorageFile> CopyAsync(IStorageFolder destinationFolder, string desiredNewName,
        NameCollisionOption option);
    IAsyncAction MoveAndReplaceAsync(IStorageFile fileToReplace);
    IAsyncAction MoveAsync(IStorageFolder destinationFolder);
    IAsyncAction MoveAsync(IStorageFolder destinationFolder, string desiredNewName);
    IAsyncAction MoveAsync(IStorageFolder destinationFolder, string desiredNewName, 
        NameCollisionOption option);
    IAsyncOperation<IRandomAccessStream> OpenAsync(FileAccessMode accessMode);
    IAsyncOperation<StorageStreamTransaction> OpenTransactedWriteAsync();
}
  • IStorageItemProperties defines members that expose a storage item's properties, such as:
    • thumbnail image
    • DisplayName (example: picture)
    • DisplayType (example: JPEG image)
    • FolderRelativeId (example: 4DE1A7035B395E15\\picture.JPG)

Use the GetScaledImageAsThumbnailAsync method of the IStorageItemProperties2 interface to obtain a file's thumbnail rather than the obsolete IStorageItemProperties.GetThumbnailAsync method. The IStorageItemProperties2 interface is implemented by both StorageFile and StorageFolder.

  • IStorageFolderQueryOperations exposes a set of operations for querying files and folders. Because a query is initiated via a root folder, only the StorageFolder class implements this interface.
  • StorageFolder is the concrete class that implements IStorageFolder, IStorageItem, IStorageItemProperties, and IStorageFolderQueryOperations. A StorageFolder may represent a physical folder on disk or a virtual folder.
  • StorageFile is the concrete class that implements IStorageFile, IStorageItem, and IStorageItemProperties. A StorageFile represents a file on disk.
  • A BasicProperties object exposes properties common to both files and folders:
    • DateModified (of type DateTimeOffset)
    • ItemDate (of type DateTimeOffset) - date released (for a song) or date taken (for a photo) etc.
    • Size (of type UInt64) - the size of the file

Shared Storage

Shared storage allows your app to communicate with other apps by exposing a file such that another app can operate on it. Access to the file is not directly granted; rather a token is generated that can then be shared between participating apps and used to access the file.

1. Add the file to the shared storage using the SharedStorageAccessManager class and return a token that represents the permission to access that file.

// Create or replace the file in the local storage.
var folder = ApplicationData.Current.LocalFolder;
var file = await folder.CreateFileAsync("test.txt", CreationCollisionOption.ReplaceExisting);
await FileIO.AppendTextAsync(file, "Testing...", Windows.Storage.Streams.UnicodeEncoding.Utf8);
 
// Add the file to the shared storage and obtain a token.
token = SharedStorageAccessManager.AddFile(file);

2. From the other app, use the token to retrieve the file using a call to RedeemTokenForFileAsync:

var file = await SharedStorageAccessManager.RedeemTokenForFileAsync(token);
if (file != null)
{
    string data = await FileIO.ReadTextAsync(file);
    Debug.WriteLine(data); // Testing...
}

ApplicationData Versioning

The ApplicationData class provides members to version the package data if you want to change the schema of the data.

public sealed class ApplicationData 
{ 
   // Members related to versioning the package's data. 
   // Typically used when the user upgrades to a new version of the package.    
   public UInt32 Version { get; }    
   public IAsyncAction SetVersionAsync( UInt32 desiredVersion, ApplicationDataSetVersionHandler handler);     
 
   // Members that clear out all (or some) of the package's per-user data    
   public IAsyncAction ClearAsync(); 
   public IAsyncAction ClearAsync(ApplicationDataLocality locality); 
 
   ...
}
// Query your packages data version number.
var appDataVersion = ApplicationData.Current.Version;
// Calling SetVersionAsync synchronously.
const UInt32 appDataLatestVersion = 2; 
if (ApplicationData.Current.Version < appDataLatestVersion) 
{
    // ApplicationData.Current.SetVersionAsync returns IAsyncAction
    ApplicationData.Current.SetVersionAsync(
        appDataLatestVersion,
        AppDataSetVersion).AsTask().GetAwaiter().GetResult();
}

The system associates a version number (a 32-bit unsigned integer) with it. By default, your package's data is assigned a version 0.

C++

Example: Writes a piece of text to a file located in the LocalFolder:

#include <sstream>
#include <string>
#include <ppltasks.h>
 
...
 
void Helpers::WriteText(std::wstring filename, std::wstring text)
{
    concurrency::create_task
    (
        Windows::Storage::ApplicationData::Current->LocalFolder->CreateFileAsync(
            Platform::StringReference(filename.c_str()),
            Windows::Storage::CreationCollisionOption::ReplaceExisting)
    )
    .then([text](Windows::Storage::StorageFile^ file)
    {
        if (file != nullptr)
        {
            concurrency::create_task
            (
                Windows::Storage::FileIO::WriteTextAsync(
                    file, 
                    Platform::StringReference(text.c_str()))
            );
        }
    });
}
notes/uwp/appdata.txt · Last modified: 2017/06/22 by leszek