C# 如何在没有 CopyFile 或 CopyFileEx 的情况下在 Windows 上复制大文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/92114/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 11:34:40  来源:igfitidea点击:

How can I copy a large file on Windows without CopyFile or CopyFileEx?

提问by Eric Z Beard

There is a limitation on Windows Server 2003 that prevents you from copying extremely large files, in proportion to the amount of RAM you have. The limitation is in the CopyFile and CopyFileEx functions, which are used by xcopy, Explorer, Robocopy, and the .NET FileInfo class.

Windows Server 2003 有一个限制,它阻止您复制与您拥有的 RAM 量成比例的超大文件。限制在于 CopyFile 和 CopyFileEx 函数,它们由 xcopy、Explorer、Robocopy 和 .NET FileInfo 类使用。

Here is the error that you get:

这是你得到的错误:

Cannot copy [filename]: Insufficient system resources exist to complete the requested service.

无法复制 [文件名]:系统资源不足,无法完成请求的服务。

The is a knowledge base articleon the subject, but it pertains to NT4 and 2000.

这是一篇关于该主题的知识库文章,但它与 NT4 和 2000 相关。

There is also a suggestion to use ESEUTILfrom an Exchange installation, but I haven't had any luck getting that to work.

还有一个建议是从 Exchange 安装中使用 ESEUTIL,但我没有运气让它起作用。

Does anybody know of a quick, easy way to handle this? I'm talking about >50Gb on a machine with 2Gb of RAM. I plan to fire up Visual Studio and just write something to do it for me, but it would be nice to have something that was already out there, stable and well-tested.

有谁知道一种快速、简单的方法来处理这个问题?我说的是在具有 2Gb RAM 的机器上 >50Gb。我计划启动 Visual Studio 并为我编写一些东西,但是如果有一些已经在那里,稳定且经过良好测试的东西会很好。

[Edit]I provided working C# code to accompany the accepted answer.

[编辑]我提供了工作 C# 代码来伴随接受的答案。

采纳答案by jabial

The best option is to just open the original file for reading, the destination file for writing and then loop copying it block by block. In pseudocode :

最好的选择是只打开原始文件进行读取,打开目标文件进行写入,然后逐块循环复制。在伪代码中:

f1 = open(filename1);
f2 = open(filename2, "w");
while( !f1.eof() ) {
  buffer = f1.read(buffersize);
  err = f2.write(buffer, buffersize);
  if err != NO_ERROR_CODE
    break;
}
f1.close(); f2.close();

[Edit by Asker]Ok, this is how it looks in C# (it's slow but it seems to work Ok, and it gives progress):

[由 Asker 编辑]好的,这就是它在 C# 中的样子(它很慢,但似乎可以正常工作,并且取得了进展):

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace LoopCopy
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length != 2)
            {
                Console.WriteLine(
                  "Usage: LoopCopy.exe SourceFile DestFile");
                return;
            }

            string srcName = args[0];
            string destName = args[1];

            FileInfo sourceFile = new FileInfo(srcName);
            if (!sourceFile.Exists)
            {
                Console.WriteLine("Source file {0} does not exist", 
                    srcName);
                return;
            }
            long fileLen = sourceFile.Length;

            FileInfo destFile = new FileInfo(destName);
            if (destFile.Exists)
            {
                Console.WriteLine("Destination file {0} already exists", 
                    destName);
                return;
            }

            int buflen = 1024;
            byte[] buf = new byte[buflen];
            long totalBytesRead = 0;
            double pctDone = 0;
            string msg = "";
            int numReads = 0;
            Console.Write("Progress: ");
            using (FileStream sourceStream = 
              new FileStream(srcName, FileMode.Open))
            {
                using (FileStream destStream = 
                    new FileStream(destName, FileMode.CreateNew))
                {
                    while (true)
                    {
                        numReads++;
                        int bytesRead = sourceStream.Read(buf, 0, buflen);
                        if (bytesRead == 0) break; 
                        destStream.Write(buf, 0, bytesRead);

                        totalBytesRead += bytesRead;
                        if (numReads % 10 == 0)
                        {
                            for (int i = 0; i < msg.Length; i++)
                            {
                                Console.Write("\b \b");
                            }
                            pctDone = (double)
                                ((double)totalBytesRead / (double)fileLen);
                            msg = string.Format("{0}%", 
                                     (int)(pctDone * 100));
                            Console.Write(msg);
                        }

                        if (bytesRead < buflen) break;

                    }
                }
            }

            for (int i = 0; i < msg.Length; i++)
            {
                Console.Write("\b \b");
            }
            Console.WriteLine("100%");
            Console.WriteLine("Done");
        }
    }
}

回答by Gulzar Nazim

If you want to write code, one way you can optimize is sending the file in chunks (like using MTOM). I used this approach for sending down huge files from a DataCenter down to our office for printing..

如果您想编写代码,可以优化的一种方法是分块发送文件(例如使用MTOM)。我使用这种方法将大文件从数据中心发送到我们的办公室进行打印。

Also, check the TeraCopy utility mentioned here..

另外,检查这里提到的 TeraCopy 实用程序..