在Windows 8中;我想将MemoryStream的内容传递给一个接受类型为Windows.Storage.Streams.IRandomAccessStream的参数的类。有没有办法将这个MemoryStream转换为IRandomAccessStream?
答案 0 :(得分: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()
从.NET流转换 - > WinRT流:
Windows.Storage.Streams.IInputStream inStream = stream.AsInputStream();
Windows.Storage.Streams.IOutputStream outStream = stream.AsOutputStream();
更新时间:2013-09-01
不要说微软不听它的开发者社区;)
在announcement for .NET FX 4.5.1中,Microsoft声明:
许多人一直想要一种将.NET Stream转换为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;
HTH。
答案 1 :(得分: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);
}
}
答案 2 :(得分: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);
}
}
更新:我还尝试了更优雅的方法实现:
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
时,我得到零。
UPDATE我更改了函数以返回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;
}
答案 3 :(得分:4)
Windows 8上没有内置方法。对于Windows 8.1,我们添加了一个Stream.AsRandomAccessStream()扩展方法:
internal static IRandomAccessStream ToRandomAccessStream(byte[] array)
{
MemoryStream stream = new MemoryStream(array);
return stream.AsRandomAccessStream();
}
答案 4 :(得分:3)
以上都不适用于我(可能是自答案发布以来的一些API更改)。唯一有效的方法是
IRandomAccessStream inMemoryStream = new InMemoryRandomAccessStream();
using (var inputStream = stream.AsInputStream())
{
await RandomAccessStream.CopyAsync(inputStream, inMemoryStream);
}
inMemoryStream.Seek(0);
答案 5 :(得分:0)
此代码段将流(stream
)转换为实现ims
的InMemoryRandomAccessStream(IRandomAccessStream
)。诀窍是必须在后台线程上调用CopyTo。
InMemoryRandomAccessStream ims = new InMemoryRandomAccessStream();
var imsWriter = ims.OpenWrite();
await Task.Factory.StartNew(() => stream.CopyTo(imsWriter));
答案 6 :(得分:0)
看一下这个链接:
How To Convert Byte Array To IRandomAccessStream
它还提供了一个字节数组构造函数的示例和实现(以及一个用于.NET流的构造函数),如果您想使用SetSource
类的SetSourceAsync
或BitmapImage
方法,则非常有用(如我的情况)。
希望这有助于某人...