Tag Archive for streams

Stream – CopyTo

Algo común en el manejo de IO en la .Net framework es el lidear con buffers y Streams, a veces simplemente necesitamos copiar el contenido de una stream hacia otra, por ejemplo, cuando necesitamos comprimir (usando GZipStream) o encriptar (usando CryptoStream). Comúnmente hacemos algo como esto:

using (var input = new MemoryStream())
using (var output = new MemoryStream()) {
    var buffer = new byte[input.Length];
    input.Read(buffer, 0, buffer.Length);
    output.Write(buffer, 0, buffer.Length);
}

Y nos topamos con siempre el pedazo de código repetitivo, además de una variable buffer la cual usamos solamente para copiar el contenido. Pues bien, en la .Net Framework 4.0 esto se simplificó un poco con el método CopyTo de la clase abstracta Stream

using (var input = new MemoryStream())
using (var output = new MemoryStream()) {
    input.CopyTo(output);
}

Bastante más conciso a mi criterio :)

Saludos!

Stream Transformations

Recuerdo que una de las primeras cosas que solíamos aprender con un lenguaje o framework era el cómo leer/escribir de o hacia un archivo (o por lo menos antes así era). En la .Net Framework tenemos todo un namespace dedicado a las operaciones de E/S de datos e información (System.IO). Una de las clases básicas en este namespace es la clase abstracta Stream. Cómo en la mayoría de lenguajes y frameworks modernas,Stream encapsula o abstrae las operaciones de E/S hacia diversos orígenes y/o destinos, de esa manera tenemos cosas como Network Streams, File Streams, Memory Streams, etc…

Algo de lo cual no muchos nos habíamos percatado es que las clases derivadas de Stream no solamente abstraen operaciones de E/S, sino que también pueden ser usadas para “transformar” datos sobre la marcha, de esa manera tenemos ya en la .Net framework clases Stream especiales como GzipStream(Compresión/Descompresión), CryptoStream (Encriptación) y me imagino que hay muchas más en la framework. Hace ya varios meses leí en la MSDN Magazine (una de mis magazines favoritas por cierto, les recomiendo a todos suscribirse :P ) un excelente artículo sobre Testing Transformation Streams (TS de aquí en adelante) y en general de que se trataba una TS y como crearla/utilizarla. Un ejemplo típico de una transformation Stream es una que elimine los espacios en una Stream básica, por ejemplo:

using System.IO;
using System.Text;
using System.Text.RegularExpressions;

namespace FilterSpacesStream
{
    public class NoSpaceStream : Stream
    {
        public NoSpaceStream(Stream sink)
        {
            Sink = sink;
        }

        private Stream Sink { get; set; }

        public override bool CanRead
        {
            get { return true; }
        }

        public override bool CanSeek
        {
            get { return Sink.CanSeek; }
        }

        public override bool CanWrite
        {
            get { return true; }
        }

        public override long Length
        {
            get { return Sink.Length; }
        }

        public override long Position
        {
            get { return Sink.Position; }
            set { Sink.Position = value; }
        }

        public override void Flush()
        {
            Sink.Flush();
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            return Sink.Seek(offset, origin);
        }

        public override void SetLength(long value)
        {
            Sink.SetLength(value);
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            return Sink.Read(buffer, offset, count);
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            string text = Encoding.UTF8.GetString(buffer);
            string result = Regex.Replace(text, @"s", string.Empty);

            byte[] data = Encoding.UTF8.GetBytes(result);
            Sink.Write(data, 0, data.Length);
        }
    }
}

Y su respectivo Fact Fixture:

using System.IO;
using System.Text;
using Xunit;

namespace FilterSpacesStream
{
    public class NoSpaceStreamFacts
    {
        private readonly MemoryStream output = new MemoryStream();
        private readonly NoSpaceStream sut;

        public NoSpaceStreamFacts()
        {
            sut = new NoSpaceStream(output);
        }

        [Fact]
        public void It_can_read()
        {
            Assert.Equal(output.CanRead, sut.CanRead);
        }

        [Fact]
        public void It_can_write()
        {
            Assert.True(sut.CanWrite);
        }

        [Fact]
        public void It_can_Seek()
        {
            Assert.Equal(output.CanSeek, sut.CanSeek);
        }

        // And many other operations I really don't want to test...

        [Fact]
        public void When_write_a_string_with_spaces_it_returns_a_string_without_spaces()
        {
            string text = "This is a test ";
            byte[] buffer = Encoding.UTF8.GetBytes(text);
            sut.Write(buffer, 0, buffer.Length);
            sut.Flush();

            buffer = output.ToArray();
            string converted = Encoding.UTF8.GetString(buffer);
            Assert.Equal("Thisisatest", converted);
        }
    }
}

Uno de los usos básicos que podríamos darle a las Transformation Streams es crear una que sobre la marcha me comprima/cambie/elimine datos en la Render Stream utilizada por la ASP.NET Framework, ven ahora hacia dónde estoy orientando este post? (Rayos, creo que pensé en “voz” alta :P )

Bueno, hasta la siguiente entrega!

Leyendo un archivo embebido en un Assembly en .Net

En la lista de correos es común leer preguntas interesantes que nos hacen dejar de hacer lo que estamos haciendo y nos obligan a escribir un pequeño post al respecto. Hoy me topo con esta interesante pero casi desconocida joya:

Compañeros, alguien conoce la forma de hacer referencia a un xml embebido en un proyecto de visual studio.

Creo que nuestro amigo se refiere a un archivo XML embebido como un “Embedded Resource” dentro de un DLL en Visual Studio. Para hacer un símil de porqué esto podría interesarle a alguien sólo recordemos que los archivos XML de mapeo de NHibernate (los hbm.xml) en la mayoría de veces estaran guardados como archivos embebidos de recurso.

La respuesta es sumamente fácil, los archivos de recurso embebidos son lo que se llama “Manifests Resource” o un recurso que viene tal como lo indicamos. Basta con usar un poco de nuestro compañero “Reflection” para leer el archivo en cuestión.

Haremos el ejemplo simple con un archivo XML:

  • Tomemos en cuenta que el archivo XML esta dentro del assembly como “Embedded Resource”.
  • El Assembly que contiene el archivo es el mismo assembly donde estamos ejecutando la aplicación.
  • Notese que el nombre del archivo es el nombre embebido MAS el namespace raíz del assembly.
using System;
using System.IO;
using System.Reflection;

namespace ReadEmbeddedResource
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var xml_filename = "ReadEmbeddedResource.Embedded.xml";
            var xml_stream = Assembly
                .GetExecutingAssembly()
                .GetManifestResourceStream(xml_filename);

            using (var sr = new StreamReader(xml_stream)) {
                Console.WriteLine(sr.ReadToEnd());
            }

            Console.ReadLine();
        }
    }
}

Y si el archivo está en otro assembly? Bien, he ahí el detalle donde el usuario debe jugar con las funciones de Assembly, nada que un rato dentro del intellisense de Visual Studio no resuelva :)