有没有办法将System.IO.Stream转换为Windows.Storage.Streams.IRandomAccessStream?

bbo*_*sak 52 .net c# windows windows-8

在Windows 8中; 我想将MemoryStream的内容传递给一个接受类型为Windows.Storage.Streams.IRandomAccessStream的参数的类.有没有办法将这个MemoryStream转换为IRandomAccessStream?

Ric*_*ner 93

要使用扩展名:您必须添加"using System.IO"

在Windows8中,.NET和WinRT类型通常在引擎盖下转换为兼容类型,因此您不必关心它.

但是,对于流,有一些帮助方法可以在WinRT和.NET流之间进行转换:对于从WinRT流转换 - > .NET流:

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

对于从.NET流转换 - > WinRT流:

Windows.Storage.Streams.IInputStream inStream = stream.AsInputStream();
Windows.Storage.Streams.IOutputStream outStream = stream.AsOutputStream();
Run Code Online (Sandbox Code Playgroud)

更新时间:2013-09-01

不要说微软不听它的开发者社区;)

.NET FX 4.5.1公告中,Microsoft声明:

你们中许多人一直想要一种方法将.NET流转换为Windows运行时IRandomAccessStream.我们只需将其称为AsRandomAccessStream扩展方法.我们无法将此功能引入Windows 8,但它是我们首次添加Windows 8.1预览版之一.

您现在可以编写以下代码,使用HttpClient下载图像,将其加载到BitmapImage中,然后设置为Xaml Image控件的源.

    //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;
Run Code Online (Sandbox Code Playgroud)

HTH.

  • 要使用这些扩展方法,您需要"使用System.IO". (7认同)
  • 这应该是答案.这很简单.使用扩展方法将WinRT流转换为.Net流. (2认同)

bbo*_*sak 7

找到更优雅的解决方案:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 不过,这个解决方案有两个问题.1)如果有人调用`GetInputStreamAt(0)`,然后调用`GetOutputStreamAt(1)`,输入流的位置也将变为`1`.2)它接受任何流,因此`CanSeek`属性可能等于`false`.在这种情况下,将抛出`NotSupportedException`.复制流对大型蒸汽的效率较低,但不应该存在这些问题. (2认同)

Rom*_*iko 5

经过一些实验,我发现以下代码正常工作.

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:我还尝试了更优雅的方法实现:

    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);
    }
Run Code Online (Sandbox Code Playgroud)

奇怪的是,它不起作用.当我stream.Size稍后打电话时,我得到零.

更新我更改了函数以返回IRandomAccessStream而不是使用回调函数

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;
}
Run Code Online (Sandbox Code Playgroud)