在C#中将大文件读入字节数组的最佳方法是什么?

11 浏览
0 Comments

在C#中将大文件读入字节数组的最佳方法是什么?

我有一个Web服务器,它会将大型二进制文件(几兆字节)读取到字节数组中。服务器可能同时读取多个文件(不同的页面请求),因此我正在寻找在不过多占用CPU资源的情况下进行此操作的最优化方法。下面的代码是否足够好? \n

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

0
0 Comments

在C#中,将大文件读入字节数组的最佳方法是什么?

有一个简单的方法可以实现这个目标:

byte[] file = System.IO.File.ReadAllBytes(fileName);

值得注意的是,当处理非常大的文件时,这种方法可能会导致程序停顿。

那么为什么会出现这个问题?原因是在使用System.IO.File.ReadAllBytes方法读取大文件时,它会一次性将整个文件读入内存,这可能会导致内存溢出或导致程序的性能下降。

为了解决这个问题,我们可以使用流来读取文件的一部分,并将其写入字节数组。这样可以避免将整个文件加载到内存中,从而提高性能并避免内存溢出。

以下是一个解决方法的示例代码:

const int bufferSize = 4096; // 缓冲区大小
byte[] file;
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
    using (BinaryReader br = new BinaryReader(fs))
    {
        long numBytes = new FileInfo(fileName).Length; // 文件大小
        long remainingBytes = numBytes;
        file = new byte[numBytes]; // 创建字节数组
        while (remainingBytes > 0)
        {
            int bytesRead = br.Read(file, (int)(numBytes - remainingBytes), bufferSize); // 从文件流中读取字节到数组中
            remainingBytes -= bytesRead;
        }
    }
}

通过使用流和缓冲区,我们可以逐步读取文件的一部分,并将其写入字节数组中。这种方法可以有效地处理大文件,并避免程序停顿或内存溢出的问题。

0
0 Comments

大文件读取为字节数组在C#中的最佳方法是什么?

在这里,我可能会认为答案通常是“不要这样做”。除非您绝对需要一次性获取所有数据,否则请考虑使用基于流的API(或一些读取器/迭代器的变体)。这在您有多个并行操作(如问题中所述)时尤为重要,以减少系统负载并最大化吞吐量。

例如,如果您正在将数据流式传输给调用方:

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

补充一下,如果您有像向客户端流式传输文件这样的I/O绑定操作,则可以考虑使用异步ASP.NET处理程序。但是,如果由于某种原因您必须将整个文件读取到byte[]中,我建议避免使用流或任何其他东西,只需使用系统提供的API。

- 同意;但是完整的上下文不清楚。同样,MVC有用于此的操作结果。

是的,我需要一次性获取所有数据。它将发送到第三方Web服务。

系统提供的API是什么?

:我在我的答案中已经说明了:File.ReadAllBytes

我如何使用它将数据写入另一个字节数组中?

通过每次更改offset来增加读取的字节数量,并通过相同数量递减要读取的数量(从bytesToRead = target.Length开始);因此:int offset = 0; int toRead = target.Length; while ((bytesRead - source.Read(target, offset, toRead)) > 0) { offset += bytesRead; toRead -= bytesRead; }

但是,当我尝试提前从源中获取长度时,代码会中断并出现SystemOutOfMemory异常。

您能展示一下您在那里做什么的代码吗?数据流有多大?是的:如果您尝试一次性将所有内容加载到内存中,它可能会爆炸;尤其是对于超过约800MiB的内容。

在您的评论中,“系统提供的API”是什么意思?

0
0 Comments

解决大文件读取到字节数组的最佳方法是使用File.ReadAllBytes方法。但是,如果担心内存消耗,应该避免一次性将整个文件读取到内存中,而应该分块读取。

File.ReadAllBytes方法在读取超过2^32字节(4.2GB)的文件时会抛出OutOfMemoryException异常。因此,对于大文件,不适合使用这种方法。

根据一位用户的建议,应该使用流的方式读取文件,而不是将其完全存储在内存中。可以参考微软官方文档中提供的方法(链接为http://msdn.microsoft.com/en-us/library/hh285054%28v=vs.110%29.aspx)。

在.NET中,数组大小有限制。但是在.NET 4.5中,可以通过特殊的配置选项打开对大数组(大于2GB)的支持(链接为http://msdn.microsoft.com/en-us/library/hh285054.aspx)。

如果只想读取文件的前x个字节(例如10个字节),那么读取全部字节的方法并不是最佳解决方案。

为了支持大对象,需要确保将解决方案的Web项目和IIS网站都设置为64位运行。

对于大文件的读取,上述方法不应该被接受或评为最佳答案。代码中给出的语句"你不应该一次性将整个文件读取到内存中,而应该分块读取"是正确的,但没有提供相应的代码。直到这部分得到解决之前,我会给予负面评价,因为这个答案的代码非常误导人,并与那个非常正确的语句相矛盾。

关于文件的编码问题,没有提供具体解决方法。

0