将汇编资源流中的文件写入磁盘

时间:2009-05-14 15:49:00

标签: c# .net

我似乎无法找到一种更有效的方法将嵌入式资源“复制”到磁盘,而不是以下方法:

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

似乎没有更直接的方式来复制,除非我遗漏了某些东西......

6 个答案:

答案 0 :(得分:65)

我不确定你为什么要使用BinaryReader / BinaryWriter。我个人会从一个有用的实用方法开始:

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

然后调用它:

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

您可以更改缓冲区大小,或者将其作为方法的参数 - 但重点是这是更简单的代码。它效率更高吗?不。你确定你真的需要这个代码更高效吗?你真的需要写出数百兆的磁盘吗?

我发现我很少需要代码来实现超高效,但我几乎总是需要它简单。您可能会在“智能”方法(如果有一种方法可用)之间看到的性能差异不太可能是复杂性变化的影响(例如O(n)到O(log n)) - 并且那是性能增益的类型,它真的值得追逐。

编辑:正如评论中所述,.NET 4.0有Stream.CopyTo所以你不需要自己编写代码。

答案 1 :(得分:58)

如果资源(文件)是二进制文件。

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

如果资源(文件)是文本。

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

答案 2 :(得分:17)

我实际上最终使用了这一行: Assembly.GetExecutingAssembly().GetManifestResourceStream("[Project].[File]").CopyTo(New FileStream(FileLocation, FileMode.Create))。当然,这是针对.Net 4.0

更新: 我发现上面的行可能会锁定文件,以便SQLite报告数据库是只读的。因此我最终得到以下结论:

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

答案 3 :(得分:2)

就我个人而言,我会这样做:

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

答案 4 :(得分:2)

如果这是你的问题,你将不得不写一个循环。但是你可以不用读写器,因为基本的Stream已经处理了byte []数据。

这就像我能得到的一样紧凑:

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

答案 5 :(得分:0)

这对我有用:

SanjayView