Hay una manera de convertir un System. IO. Stream a un Windows.Almacenamiento.Flujo.IRandomAccessStream?


En Windows 8; Me gustaría pasar el contenido de un MemoryStream a una clase que acepte un parámetro de tipo Windows.Almacenamiento.Flujo.IRandomAccessStream. ¿Hay alguna manera de convertir este MemoryStream a un IRandomAccessStream?

Author: IDWMaster, 2011-10-06

7 answers

Para usar las extensiones: debe agregar "usando System.IO"

En Windows8, los tipos.NET y WinRT generalmente se convierten a/desde tipos compatibles bajo el capó, por lo que no tiene que preocuparse por ello.

Para flujos, sin embargo, hay métodos auxiliares para convertir entre flujos WinRT y. NET: Para convertir de secuencias WinRT - > secuencias. NET:

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

Para la conversión de secuencias. NET - > secuencias WinRT:

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

ACTUALIZAR: 2013-09-01

Que no se dice que Microsoft no escucha a su comunidad de desarrolladores;)

En el anuncio de para. NET FX 4.5.1, Microsoft afirma que:

Muchos de ustedes han estado queriendo una forma de convertir una transmisión. NET a un IRandomAccessStream de tiempo de ejecución de Windows. Vamos a llamarlo un método de extensión AsRandomAccessStream. No pudimos obtener esta función en Windows 8, pero fue una de nuestras primeras adiciones a Windows 8.1 Preview.

Ahora puedes escriba el siguiente código, para descargar una imagen con HttpClient, cárguela en una BitmapImage y luego establezca como fuente para un control de imagen 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.

 93
Author: Rich Turner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-01 18:40:47

Encontró una solución más elegante:

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);
    }
}
 7
Author: IDWMaster,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-03 13:03:50

Después de experimentar, encontré que el siguiente código estaba funcionando.

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

ACTUALIZACIÓN: También probé la implementación del método más elegante:

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

Extrañamente, no funciona. Cuando llamo stream.Size más tarde, obtengo cero.

ACTUALIZACIÓN Cambié la función para devolver el IRandomAccessStream en lugar de usar la función 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;
}
 5
Author: Roman Boiko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-03 01:10:22

No hay un método integrado en Windows 8. Para Windows 8.1 hemos añadido una secuencia.Método de extensión AsRandomAccessStream ():

internal static IRandomAccessStream ToRandomAccessStream(byte[] array)
{
    MemoryStream stream = new MemoryStream(array);
    return stream.AsRandomAccessStream();
}
 4
Author: Immo Landwerth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-28 00:21:11

Nada de lo anterior funciona para mí hoy (tal vez algunos cambios en la API desde que se publicaron las respuestas). La única manera que funciona es

IRandomAccessStream inMemoryStream = new InMemoryRandomAccessStream();
using (var inputStream = stream.AsInputStream())
{
    await RandomAccessStream.CopyAsync(inputStream, inMemoryStream);
}
inMemoryStream.Seek(0);
 3
Author: Igor Kulman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-12 10:17:06

Este fragmento de código convierte un flujo (stream) en un InMemoryRandomAccessStream (ims) que implementa IRandomAccessStream. El truco es que CopyTo tiene que ser llamado en un hilo de fondo.

        InMemoryRandomAccessStream ims = new InMemoryRandomAccessStream();
        var imsWriter = ims.OpenWrite();
        await Task.Factory.StartNew(() => stream.CopyTo(imsWriter));
 0
Author: Robert Levy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-14 16:46:28

Echa un vistazo a este enlace:

Cómo Convertir Una Matriz De Bytes A IRandomAccessStream

También da ejemplos y una implementación de un constructor de matriz de bytes (y uno para flujos.NET), útil si desea usar los métodos SetSource o SetSourceAsync de la clase BitmapImage (como en mi caso).

Espero que esto ayude a alguien...

 0
Author: MAXE,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-28 08:17:30