11

我正在使用此代码从文件中提取一个块

// info is FileInfo object pointing to file
var percentSplit = info.Length * 50 / 100; // extract 50% of file
var bytes = new byte[percentSplit];
var fileStream = File.OpenRead(fileName);
fileStream.Read(bytes, 0, bytes.Length);
fileStream.Dispose();
File.WriteAllBytes(splitName, bytes);

有什么方法可以加快这个过程吗?

目前,对于 530 MB 的文件,大约需要 4 - 5 秒。这个时间可以改善吗?

4

4 回答 4

8

您有几个问题的案例,但没有一个与语言相关

以下是需要关注的问题

  • 源/目标文件的文件系统是什么?
  • 您要保留原始源文件吗?
  • 它们位于同一个驱动器上吗?

在 C# 中,您几乎没有一种方法可以比内部File.Copy调用更快。但是,由于百分比是 50,因此下面的代码可能不会更快。它复制整个文件,然后设置目标文件的长度CopyFileWINAPI

var info=new FileInfo(fileName);
var percentSplit=info.Length*50/100; // extract 50% of file

File.Copy(info.FullName, splitName);
using(var outStream=File.OpenWrite(splitName))
    outStream.SetLength(percentSplit);

此外,如果

  1. 文件拆分后您不保留原始源
  2. 目标驱动器与源驱动器相同
  3. 您没有使用启用加密/压缩的文件系统

那么,你能做的最好的事情就是不要复制文件。例如,如果您的源文件位于FATFAT32文件系统上,您可以做的是

  1. 为文件的新拆分部分创建新的目录条目(条目)
  2. 让条目(条目)指向目标部分的集群
  3. 为每个条目设置正确的文件大小
  4. 检查交叉链接并避免这种情况

如果您的文件系统是NTFS,您可能需要花费很长时间来研究规范。

祝你好运!

于 2013-02-10T11:56:01.460 回答
2
var percentSplit = (int)(info.Length * 50 / 100); // extract 50% of file
var buffer = new byte[8192];
using (Stream input = File.OpenRead(info.FullName))
using (Stream output = File.OpenWrite(splitName))
{
    int bytesRead = 1;
    while (percentSplit > 0 && bytesRead > 0)
    {
        bytesRead = input.Read(buffer, 0, Math.Min(percentSplit, buffer.Length));
        output.Write(buffer, 0, bytesRead);
        percentSplit -= bytesRead;
    }
    output.Flush();
}

可能不需要刷新,但它不会造成伤害,这很有趣,将循环更改为do-while而不是while对性能有很大影响。我想IL没有那么快。我的电脑在 4-6 秒内运行原始代码,附加代码似乎在 1 秒左右运行。

于 2013-02-25T18:27:57.967 回答
0

当读取/写入几兆字节的块时,我会得到更好的结果。性能也会根据块的大小而变化。

FileInfo info = new FileInfo(@"C:\source.bin");
FileStream f = File.OpenRead(info.FullName);
BinaryReader br = new BinaryReader(f);

FileStream t = File.OpenWrite(@"C:\split.bin");
BinaryWriter bw = new BinaryWriter(t);

long count = 0;
long split = info.Length * 50 / 100;
long chunk = 8000000;

DateTime start = DateTime.Now;

while (count < split)
{
    if (count + chunk > split)
    {
        chunk = split - count;
    }

    bw.Write(br.ReadBytes((int)chunk));
    count += chunk;
}

Console.WriteLine(DateTime.Now - start);
于 2013-02-11T12:21:13.760 回答
-1

我认为解决这个问题的最快方法是通过二进制缓冲文件输入。

我在 C# 中不是很熟悉,但是您可以研究一些缓冲技术来转到文件的特定部分,并从该部分进行缓冲输入。

您还可以使用带有 Windows API 的 C++ 来实现本机缓冲技术,或者查找具有快速缓冲方法的库。

我不能提出太多其他建议,希望这会有所帮助。

于 2013-02-10T04:16:28.343 回答