有没有办法将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
类的SetSource
或SetSourceAsync
方法(就像我的情况一样),那么这个方法很有用。
希望这可以帮助别人…