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

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

要使用扩展名:您必须添加“使用System.IO”

在Windows8中,.NET和WinRTtypes通常转换为兼容types,因此您不必关心它。

然而,对于stream,有一些帮助方法可以在WinRT和.NETstream之间进行转换:从WinRTstream转换 – > .NETstream:

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

从.NETstream转换 – > WinRTstream:

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

更新:2013-09-01

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

在.NET FX 4.5.1的公告中 ,微软表示:

你们中许多人一直想要一种方法来将.NET Stream转换为Windows运行时IRandomAccessStream。 我们把它叫做AsRandomAccessStream扩展方法。 我们无法将这个functionjoin到Windows 8中,但这是我们第一次joinWindows 8.1 Preview。

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

  //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。

find更优雅的解决scheme:

 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); } } 

经过一番尝试,我发现以下代码正在工作。

 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); } } 

更新:我也试过更优雅的方法实现:

  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); } 

奇怪的是,这是行不通的。 当我稍后调用stream.Size ,我得到零。

更新我改变了函数返回IRandomAccessStream而不是使用callback函数

 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; } 

在Windows 8上没有内置的方法。对于Windows 8.1,我们添加了一个Stream.AsRandomAccessStream()扩展方法:

 internal static IRandomAccessStream ToRandomAccessStream(byte[] array) { MemoryStream stream = new MemoryStream(array); return stream.AsRandomAccessStream(); } 

以上这些都不适合我(也许自发布答案以来发生了一些API更改)。 唯一可行的方法是

 IRandomAccessStream inMemoryStream = new InMemoryRandomAccessStream(); using (var inputStream = stream.AsInputStream()) { await RandomAccessStream.CopyAsync(inputStream, inMemoryStream); } inMemoryStream.Seek(0); 

这段代码将一个stream( stream )转换成实现IRandomAccessStream的InMemoryRandomAccessStream( ims )。 诀窍是CopyTo必须在后台线程上调用。

  InMemoryRandomAccessStream ims = new InMemoryRandomAccessStream(); var imsWriter = ims.OpenWrite(); await Task.Factory.StartNew(() => stream.CopyTo(imsWriter)); 

看看这个链接:

如何将字节数组转换为IRandomAccessStream

它也给出了一个字节数组构造函数(和一个用于.NETstream)的示例和实现,如果您想要使用BitmapImage类的SetSourceSetSourceAsync方法(就像我的情况一样),那么这个方法很有用。

希望这可以帮助别人…