【问题标题】:How can I copy a large file on Windows without CopyFile or CopyFileEx?如何在没有 CopyFile 或 CopyFileEx 的情况下在 Windows 上复制大文件?
【发布时间】:2008-09-18 12:33:05
【问题描述】:

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

这是您得到的错误:

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

主题是knowledge base article,但它属于 NT4 和 2000。

还有一个从 Exchange 安装到use ESEUTIL 的建议,但我没有任何运气让它工作。

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

[编辑]我提供了有效的 C# 代码来配合接受的答案。

【问题讨论】:

    标签: c# windows file-io


    【解决方案1】:

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

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

    [由 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");
            }
        }
    }
    

    【讨论】:

    • 使用至少 100KB 更好的 1MB 缓冲区。这将大大加快文件复制速度!
    • 你有 2 GB 的空间可以玩...... ;) 说真的,Aaron 是对的 - 增加读/写缓冲区。
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2019-04-11
      • 1970-01-01
      • 2023-03-30
      • 2021-07-29
      • 1970-01-01
      • 1970-01-01
      • 2020-09-21
      • 2021-11-24
      • 2020-10-28
      相关资源
      最近更新 更多