1

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.

Chris Watts
  • 822
  • 1
  • 9
  • 27

1 Answers1

1

...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();
Rita Han
  • 9,574
  • 1
  • 11
  • 24
  • Hi, thanks for the response, with regards to creating a stream, the stream returned by OpenAsync is of type `IAsyncOperation`, unfortunately, not compatible with System.IO.Stream that the constructor supports. Looking at the `PublisherCacheFolder` information, its a way of specifying folder paths, i cannot find any information online to indicate whether you can give it a whole path to an external drive? Is that possible through using `D:\folder` in the xml configuration? Thanks for your help! – Chris Watts May 15 '17 at 10:56
  • You can use `KnownFolders.RemovableDevices` to get the external drive. – Rita Han May 16 '17 at 03:07
  • yes i have the storage file object for the removable drive already, just needed a way to get a stream to use the external drive as a database directory rather than the path, which i think will prohibit access. – Chris Watts May 16 '17 at 04:21
  • It looks like there are multi questions. Please check the update of my answer of converting `IRandomAccessStream` to `System.IO.Stream` To be clear, you can show your code in your question and point out where you are stuck or what error info you get. – Rita Han May 16 '17 at 05:49
  • 1
    Thanks, that addition works to convert the `RandomAccessStream` to `IO.Stream`, not sure where the confusion is about my question as I did mention that I was getting the `IAsyncOperation`, needed a `System.IO.Stream`, with the purpose of writing an external drive that I already had the access to and was being provided a `StorageFile` object of. The code I provided was the entire problem I had, an `OpenAsync` would return the wrong type of stream required for the LiteDb constructor. Thanks for your help, sorry if I caused confusion? – Chris Watts May 16 '17 at 09:03