Search code examples
c#uwpwindowsiotlitedb

Creating a LiteDb database with a StorageFile argument


I am trying to implement a database provider using LiteDb on my raspberry pi using UWP. It has an external hard drive attached and I would very much like to use it as a specific "Database" drive, to allow me to have a larger supported database size.

I am being passed a StorageFile, which is then to be used as my Database file. One constructor on LiteDb uses a stream (System.IO.Stream), is there anyway to convert the StorageFile object into a stream (derived from System.IO.Stream) in order to fulfill the new win10 security restrictions (requiring user permissions to access areas etc., preventing traditional File.Write/path based access to anything other than your application data directory).

Really am stuck, the option I have tried, which gives both read and write access to the StorageFile is:

var stream = storageProvider.StorageLocaton.OpenAsync(FileAccessMode.ReadWrite);

Unfortunately, I cannot find any other methods which give both read/write access to the file as a stream.

Hopefully someone on here has a work around/solution.


Solution

  • ...is there anyway to convert the StorageFile object into a stream...

    You can use StorageFile.OpenAsync(FileAccessMode.ReadWrite) for writing and StorageFile.OpenAsync(FileAccessMode.Read) for reading.

    As for

    win10 security restrictions (requiring user permissions to access areas etc., preventing traditional File.Write/path based access to anything other than your application data directory).

    You can utilize PublisherCacheFolder:

    The strong security model of Windows Runtime app typically prevents apps from sharing data among themselves. It can be useful, however, for apps from the same publisher to share files and settings on a per-user basis. As an app publisher, you can register your app to share a storage folder with other apps that you publish by adding extensions to the app manifest.

    The following code piece you can reference:

            StorageFolder sharedFonts = Windows.Storage.ApplicationData.Current.GetPublisherCacheFolder("test");
            var testFile = await sharedFonts.CreateFileAsync("test.txt", CreationCollisionOption.OpenIfExists);
    
            var byteArray = new byte[] { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a };
            using (var sourceStream = new MemoryStream(byteArray).AsRandomAccessStream())
            {
                using (var destinationStream = (await testFile.OpenAsync(FileAccessMode.ReadWrite)).GetOutputStreamAt(0))
                {
                    await RandomAccessStream.CopyAndCloseAsync(sourceStream, destinationStream);
                }
            }
    
            var readArray = new byte[100];
            using (var destinationStream = new MemoryStream(readArray).AsRandomAccessStream())
            {
                using (var sourceStream = (await testFile.OpenAsync(FileAccessMode.Read)).GetInputStreamAt(0))
                {
                    await RandomAccessStream.CopyAndCloseAsync(sourceStream, destinationStream);
                }
            }
    

    Update:

    You can convert IRandomAccessStream to System.IO.Stream like this:

    Stream writeStream = destinationStream.AsStreamForWrite();
    
    Stream readStream = sourceStream.AsStreamForRead();