我有一个网络服务器,它将读取大二进制文件(几兆字节)到字节数组。服务器可能同时读取多个文件(不同的页面请求),因此我正在寻找一种最优化的方式来执行此操作,而不会对CPU造成太多负担。下面的代码足够好吗?

public byte[] FileToByteArray(string fileName)
{
    byte[] buff = null;
    FileStream fs = new FileStream(fileName, 
                                   FileMode.Open, 
                                   FileAccess.Read);
    BinaryReader br = new BinaryReader(fs);
    long numBytes = new FileInfo(fileName).Length;
    buff = br.ReadBytes((int) numBytes);
    return buff;
}

当前回答

我可能会说,这里的答案通常是“不”。除非你绝对需要一次性获得所有数据,否则可以考虑使用基于流的API(或者reader / iterator的一些变体)。当您有多个并行操作(正如问题所建议的)以最小化系统负载和最大化吞吐量时,这一点尤其重要。

例如,如果您正在向调用者传输数据:

Stream dest = ...
using(Stream source = File.OpenRead(path)) {
    byte[] buffer = new byte[2048];
    int bytesRead;
    while((bytesRead = source.Read(buffer, 0, buffer.Length)) > 0) {
        dest.Write(buffer, 0, bytesRead);
    }
}

其他回答

如果您正在处理大于2 GB的文件,您会发现上述方法失败。

直接将流交给MD5并允许它为你分块文件要容易得多:

private byte[] computeFileHash(string filename)
{
    MD5 md5 = MD5.Create();
    using (FileStream fs = new FileStream(filename, FileMode.Open))
    {
        byte[] hash = md5.ComputeHash(fs);
        return hash;
    }
}

我可能会说,这里的答案通常是“不”。除非你绝对需要一次性获得所有数据,否则可以考虑使用基于流的API(或者reader / iterator的一些变体)。当您有多个并行操作(正如问题所建议的)以最小化系统负载和最大化吞吐量时,这一点尤其重要。

例如,如果您正在向调用者传输数据:

Stream dest = ...
using(Stream source = File.OpenRead(path)) {
    byte[] buffer = new byte[2048];
    int bytesRead;
    while((bytesRead = source.Read(buffer, 0, buffer.Length)) > 0) {
        dest.Write(buffer, 0, bytesRead);
    }
}

你的代码可以分解成这个(代替File.ReadAllBytes):

public byte[] ReadAllBytes(string fileName)
{
    byte[] buffer = null;
    using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
    {
        buffer = new byte[fs.Length];
        fs.Read(buffer, 0, (int)fs.Length);
    }
    return buffer;
} 

注意整数。MaxValue -由Read方法设置的文件大小限制。换句话说,一次只能读取2GB的数据块。

还要注意FileStream的最后一个参数是缓冲区大小。

我还建议阅读FileStream和BufferedStream。

一如既往,一个简单的示例程序来分析哪个是最快的将是最有益的。

此外,底层硬件对性能也有很大影响。您是否使用基于服务器的具有大缓存的硬盘驱动器和带有板载内存缓存的RAID卡?还是使用连接到IDE端口的标准驱动器?

用这个:

 bytesRead = responseStream.ReadAsync(buffer, 0, Length).Result;

我建议尝试Response.TransferFile()方法,然后使用Response.Flush()和Response.End()来提供大文件。