30 votos

Escribir en el archivo de la asamblea flujo de recursos en el disco

Me parece que no puede encontrar una manera más eficiente para "copiar" un recurso incrustado en el disco, de la siguiente manera:

using (BinaryReader reader = new BinaryReader(
    assembly.GetManifestResourceStream(@"Namespace.Resources.File.ext")))
{
    using (BinaryWriter writer
        = new BinaryWriter(new FileStream(path, FileMode.Create)))
    {
        long bytesLeft = reader.BaseStream.Length;
        while (bytesLeft > 0)
        {
            // 65535L is < Int32.MaxValue, so no need to test for overflow
            byte[] chunk = reader.ReadBytes((int)Math.Min(bytesLeft, 65536L));
            writer.Write(chunk);

            bytesLeft -= chunk.Length;
        }
    }
}

Parece ser que no hay manera más directa para hacer la copia, a menos que me estoy perdiendo algo...

49voto

Jon Skeet Puntos 692016

No estoy seguro de por qué usted está usando BinaryReader/BinaryWriter en todo. Personalmente me gustaría empezar con un útil método de utilidad:

public static void CopyStream(Stream input, Stream output)
{
    // Insert null checking here for production
    byte[] buffer = new byte[8192];

    int bytesRead;
    while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
    {
        output.Write(buffer, 0, bytesRead);
    }
}

a continuación, llame a:

using (Stream input = assembly.GetManifestResourceStream(resourceName))
using (Stream output = File.Create(path))
{
    CopyStream(input, output);
}

Usted puede cambiar el tamaño de búfer de curso, o la tienen como un parámetro para el método - pero el punto principal es que esto es más sencillo código. Es más eficiente? Nope. Está usted seguro de que usted realmente necesita este código para ser más eficientes? ¿Usted realmente tiene cientos de megabytes que usted necesita para escribir en el disco?

Me parece que rara vez se necesita código para ser ultra-eficiente, pero yo casi siempre se necesita para ser simple. El tipo de diferencia en el rendimiento que se pueden ver entre esto y un "inteligente" enfoque (si está disponible) no es probable que sea la complejidad de un efecto de cambio (por ejemplo, de O(n) O(log n)) - y ese es el tipo de rendimiento de la ganancia que puede ser realmente vale la pena perseguir.

EDIT: Como se señaló en los comentarios, .NET 4.0 Stream.CopyTo así que usted no necesita código de este mismo.

28voto

KoalaBear Puntos 653

Lamento post a un hilo viejo, pero descubrió una manera más fácil aún si el recurso (archivo) es binario.

File.WriteAllBytes("C:\ResourceName", Resources.ResourceName);

8voto

cjbarth Puntos 838

De hecho, me terminó la utilización de esta línea: Assembly.GetExecutingAssembly().GetManifestResourceStream("[Project].[File]").CopyTo(New FileStream(FileLocation, FileMode.Create)). Por supuesto, esto es para .Net 4.0

Actualización: He encontrado que la línea de arriba podría mantener un archivo bloqueado tal que SQLite informes de que la base de datos es de sólo lectura. Por lo tanto, que terminó con la siguiente:

Using newFile As Stream = New FileStream(FileLocation, FileMode.Create)
    Assembly.GetExecutingAssembly().GetManifestResourceStream("[Project].[File]").CopyTo(newFile)
End Using

2voto

Lloyd Puntos 16334

Personalmente, me haría de esta manera:

using (BinaryReader reader = new BinaryReader(
    assembly.GetManifestResourceStream(@"Namespace.Resources.File.ext")))
{
    using (BinaryWriter writer
        = new BinaryWriter(new FileStream(path, FileMode.Create)))
    {
        byte[] buffer = new byte[64 * 1024];
        int numread = reader.Read(buffer,0,buffer.Length);

        while (numread > 0)
        {
            writer.Write(buffer,0,numread);
            numread = reader.Read(buffer,0,buffer.Length);
        }

        writer.Flush();
    }
}

2voto

Henk Holterman Puntos 153608

Usted tendrá que escribir un bucle, si esa es tu pregunta. Pero se puede hacer sin el lector y el escritor ya que la base de Arroyo ya se ocupa de byte[] datos.

Esto es tan compacto como puedo conseguir:

using (Stream inStream = File.OpenRead(inputFile))
using (Stream outStream = File.OpenWrite(outputFile))
{
    int read;
    byte[] buffer = new byte[64 * 1024];

    while ((read = inStream.Read(buffer, 0, buffer.Length)) > 0)
    {
        outStream.Write(buffer, 0, read);
    }
}

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by: