Is there a way to convert a System.IO.Stream to a Windows.Storage.Streams.IRandomAccessStream?

后端 未结 7 933
暖寄归人
暖寄归人 2020-11-30 00:42

In Windows 8; I would like to pass the contents of a MemoryStream to a class that accepts a parameter of type Windows.Storage.Streams.IRandomAccessStream. Is there any way t

相关标签:
7条回答
  • 2020-11-30 00:56

    Found a more elegant solution:

    public static class MicrosoftStreamExtensions
    {
        public static IRandomAccessStream AsRandomAccessStream(this Stream stream)
        {
            return new RandomStream(stream);
        }
    
    }
    
    class RandomStream : IRandomAccessStream
    {
        Stream internstream;
    
        public RandomStream(Stream underlyingstream)
        {
            internstream = underlyingstream;
        }
    
        public IInputStream GetInputStreamAt(ulong position)
        {
            //THANKS Microsoft! This is GREATLY appreciated!
            internstream.Position = (long)position;
            return internstream.AsInputStream();
        }
    
        public IOutputStream GetOutputStreamAt(ulong position)
        {
            internstream.Position = (long)position;
            return internstream.AsOutputStream();
        }
    
        public ulong Size
        {
            get
            {
                return (ulong)internstream.Length;
            }
            set
            {
                internstream.SetLength((long)value);
            }
        }
    
        public bool CanRead
        {
            get { return this.internstream.CanRead; }
        }
    
        public bool CanWrite
        {
            get { return this.internstream.CanWrite; }
        }
    
        public IRandomAccessStream CloneStream()
        {
            throw new NotSupportedException();
        }
    
        public ulong Position
        {
            get { return (ulong)this.internstream.Position; }
        }
    
        public void Seek(ulong position)
        {
            this.internstream.Seek((long)position, SeekOrigin.Begin);
        }
    
        public void Dispose()
        {
            this.internstream.Dispose();
        }
    
        public Windows.Foundation.IAsyncOperationWithProgress ReadAsync(IBuffer buffer, uint count, InputStreamOptions options)
        {
            return this.GetInputStreamAt(this.Position).ReadAsync(buffer, count, options);
        }
    
        public Windows.Foundation.IAsyncOperation FlushAsync()
        {
            return this.GetOutputStreamAt(this.Position).FlushAsync();
        }
    
        public Windows.Foundation.IAsyncOperationWithProgress WriteAsync(IBuffer buffer)
        {
            return this.GetOutputStreamAt(this.Position).WriteAsync(buffer);
        }
    }
    0 讨论(0)
  • 2020-11-30 00:56

    None of the above works for me today (maybe some API changes since the answers were posted). The only way that works is

    IRandomAccessStream inMemoryStream = new InMemoryRandomAccessStream();
    using (var inputStream = stream.AsInputStream())
    {
        await RandomAccessStream.CopyAsync(inputStream, inMemoryStream);
    }
    inMemoryStream.Seek(0);
    
    0 讨论(0)
  • 2020-11-30 01:03

    This code snippet turns a stream (stream) into an InMemoryRandomAccessStream (ims) which implement IRandomAccessStream. The trick is that CopyTo has to be called on a background thread.

            InMemoryRandomAccessStream ims = new InMemoryRandomAccessStream();
            var imsWriter = ims.OpenWrite();
            await Task.Factory.StartNew(() => stream.CopyTo(imsWriter));
    
    0 讨论(0)
  • 2020-11-30 01:04

    To use the extensions: you must add "using System.IO"

    In Windows8, .NET and WinRT types are generally converted to/from compatible types under the hood so you don't have to care about it.

    For streams, however, there are helper methods to convert between WinRT and .NET streams: For converting from WinRT streams -> .NET streams:

    InMemoryRandomAccessStream win8Stream = GetData(); // Get a data stream from somewhere.
    System.IO.Stream inputStream = win8Stream.AsStream()
    

    For converting from .NET streams -> WinRT streams:

    Windows.Storage.Streams.IInputStream inStream = stream.AsInputStream();
    Windows.Storage.Streams.IOutputStream outStream = stream.AsOutputStream();
    

    UPDATE: 2013-09-01

    Let it not be said that Microsoft doesn't listen to it's developer community ;)

    In the announcement for .NET FX 4.5.1, Microsoft states that:

    Many of you have been wanting a way to convert a .NET Stream to a Windows Runtime IRandomAccessStream. Let’s just call it an AsRandomAccessStream extension method. We weren't able to get this feature into Windows 8, but it was one of our first additions to Windows 8.1 Preview.

    You can now write the following code, to download an image with HttpClient, load it in a BitmapImage and then set as the source for a Xaml Image control.

        //access image via networking i/o
        var imageUrl = "http://www.microsoft.com/global/en-us/news/publishingimages/logos/MSFT_logo_Web.jpg";
        var client = new HttpClient();
        Stream stream = await client.GetStreamAsync(imageUrl);
        var memStream = new MemoryStream();
        await stream.CopyToAsync(memStream);
        memStream.Position = 0;
        var bitmap = new BitmapImage();
        bitmap.SetSource(memStream.AsRandomAccessStream());
        image.Source = bitmap;
    

    HTH.

    0 讨论(0)
  • 2020-11-30 01:06

    Take a look to this link:

    How To Convert Byte Array To IRandomAccessStream

    It also gives examples and an implementation of a byte array constructor (and one for .NET streams), useful if you want to use the SetSource or SetSourceAsync methods of BitmapImage class (as in my case).

    Hope this helps someone...

    0 讨论(0)
  • 2020-11-30 01:08

    After some experimenting I found the following code to be working.

    using System;
    using System.IO;
    using System.Threading.Tasks;
    using Windows.Storage.Streams;
    
    partial class MainPage
    {
        public MainPage()
        {
            var memoryStream = new MemoryStream(new byte[] { 65, 66, 67 });
            ConvertToRandomAccessStream(memoryStream, UseRandomAccessStream);
            InitializeComponent();
        }
    
        void UseRandomAccessStream(IRandomAccessStream stream)
        {
            var size = stream.Size;
        } // put breakpoint here to check size
    
        private static async void ConvertToRandomAccessStream(MemoryStream memoryStream,
             Action<IRandomAccessStream> callback)
        {
            var randomAccessStream = new InMemoryRandomAccessStream();
            var outputStream = randomAccessStream.GetOutputStreamAt(0);
            var dw = new DataWriter(outputStream);
            var task = new Task(() => dw.WriteBytes(memoryStream.ToArray()));
            task.Start();
            await task;
            await dw.StoreAsync();
            var success = await outputStream.FlushAsync();
            callback(randomAccessStream);
        }
    }
    

    UPDATE: I also tried more elegant method implementation:

        private static void ConvertToRandomAccessStream(MemoryStream memoryStream,
            Action<IRandomAccessStream> callback)
        {
            var randomAccessStream = new InMemoryRandomAccessStream();
            var outputStream = randomAccessStream.GetOutputStreamAt(0);
            RandomAccessStream.Copy(memoryStream.AsInputStream(), outputStream);
            callback(randomAccessStream);
        }
    

    Strangely, it doesn't work. When I call stream.Size later, I get zero.

    UPDATE I changed the function to return the IRandomAccessStream rather than using the callback function

    public static async Task<IRandomAccessStream> ConvertToRandomAccessStream(MemoryStream memoryStream)
    {
        var randomAccessStream = new InMemoryRandomAccessStream();
    
        var outputStream = randomAccessStream.GetOutputStreamAt(0);
        var dw = new DataWriter(outputStream);
        var task = new Task(() => dw.WriteBytes(memoryStream.ToArray()));
        task.Start();
    
        await task;
        await dw.StoreAsync();
    
        await outputStream.FlushAsync();
    
        return randomAccessStream;
    }
    
    0 讨论(0)
提交回复
热议问题