如何有效地拆分大文件

我想知道如何在不使用太多系统资源的情况下拆分大文件。 我目前正在使用此代码:

public static void SplitFile(string inputFile, int chunkSize, string path) { byte[] buffer = new byte[chunkSize]; using (Stream input = File.OpenRead(inputFile)) { int index = 0; while (input.Position < input.Length) { using (Stream output = File.Create(path + "\\" + index)) { int chunkBytesRead = 0; while (chunkBytesRead < chunkSize) { int bytesRead = input.Read(buffer, chunkBytesRead, chunkSize - chunkBytesRead); if (bytesRead == 0) { break; } chunkBytesRead += bytesRead; } output.Write(buffer, 0, chunkBytesRead); } index++; } } } 

该操作需要52.370秒才能将1.6GB文件拆分为14mb文件。 我不关心操作需要多长时间,我更关心使用的系统资源,因为此应用程序将部署到共享托管环境。 目前,此操作最大化了我的系统HDD IO使用率100%,并大大减慢了我的系统速度。 CPU使用率低; RAM略微上升,但看起来很好。

有没有办法可以限制此操作使用太多资源?

谢谢

将每个输出文件组装在内存中似乎很奇怪; 我怀疑你应该运行一个内部缓冲区(可能是20k或其他东西)并更频繁地调用Write

最终,如果您需要IO,则需要IO。 如果你想对共享的托管环境保持礼貌,你可以添加故意的暂停 – 可能是内循环中的短暂暂停,以及外循环中的较长暂停(可能是1s)。 这不会对您的总体时间造成太大影响,但可能有助于其他进程获得一些IO。

内循环的缓冲区示例:

 public static void SplitFile(string inputFile, int chunkSize, string path) { const int BUFFER_SIZE = 20 * 1024; byte[] buffer = new byte[BUFFER_SIZE]; using (Stream input = File.OpenRead(inputFile)) { int index = 0; while (input.Position < input.Length) { using (Stream output = File.Create(path + "\\" + index)) { int remaining = chunkSize, bytesRead; while (remaining > 0 && (bytesRead = input.Read(buffer, 0, Math.Min(remaining, BUFFER_SIZE))) > 0) { output.Write(buffer, 0, bytesRead); remaining -= bytesRead; } } index++; Thread.Sleep(500); // experimental; perhaps try it } } } 

我已经修改了问题中的代码,以防你想要按块分割,同时确保每个块结束一行结束:

  private static void SplitFile(string inputFile, int chunkSize, string path) { byte[] buffer = new byte[chunkSize]; List extraBuffer = new List(); using (Stream input = File.OpenRead(inputFile)) { int index = 0; while (input.Position < input.Length) { using (Stream output = File.Create(path + "\\" + index + ".csv")) { int chunkBytesRead = 0; while (chunkBytesRead < chunkSize) { int bytesRead = input.Read(buffer, chunkBytesRead, chunkSize - chunkBytesRead); if (bytesRead == 0) { break; } chunkBytesRead += bytesRead; } byte extraByte = buffer[chunkSize - 1]; while (extraByte != '\n') { int flag = input.ReadByte(); if (flag == -1) break; extraByte = (byte)flag; extraBuffer.Add(extraByte); } output.Write(buffer, 0, chunkBytesRead); if (extraBuffer.Count > 0) output.Write(extraBuffer.ToArray(), 0, extraBuffer.Count); extraBuffer.Clear(); } index++; } } } 

目前,此操作最大化了我的系统HDD IO使用率为100%。

这是合乎逻辑的 – IO将成为您的限制因素,您的系统可能具有与大多数计算机相同的蹩脚IO(一个慢速光盘,而不是高性能光盘的RAID 10)。

你可以使用一个体面的块sze(向上1mb)来减少小的读写,但最后你可以这样做。 或者获得更快的光盘子系统。

您拥有的选项是限制操作。 如果您将缓冲区恢复到较小的大小(介于4K和1MB之间)并在操作之间放置Thread.Sleep,则将使用较少的资源。

对于您的主机而言,这是一个问题,而不是您。 假设这绝对是你需要做的事情,那么你几乎可以以最有效的方式做到这一点。 它们由负载,优先级,SLA等管理资源,与Hypervisor / VM / OS / App Server /无论如何相同。

拆开文件并使用您已支付的设施!