如何在没有CopyFile或CopyFileEx的情况下在Windows上复制大文件? [英] How can I copy a large file on Windows without CopyFile or CopyFileEx?

查看:723
本文介绍了如何在没有CopyFile或CopyFileEx的情况下在Windows上复制大文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Windows Server 2003有一个限制,可以防止您复制超大文件,与您拥有的RAM数量成比例。限制在CopyFile和CopyFileEx函数中,这些函数由xcopy,Explorer,Robocopy和.NET FileInfo类使用。



以下是您遇到的错误:
$ b


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


这是知识库文章关于这个问题,但它适用于NT4和2000.



还有一个建议使用ESEUTIL 从Exchange安装,但我没有任何运气得到工作。



有人知道一个快速,简单的方法来处理这个问题吗?我在2Gb内存的机器上谈论> 50Gb。我打算启动Visual Studio,只是写一些东西给我,但是能够有一些已经存在的东西,稳定和经过很好的测试。



我提供了工作的C#代码来陪同接受的答案。

选项是刚刚打开原来的文件进行读取,写入的目标文件,然后循环逐块复制它。伪代码:

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

好的,这是C# (这很慢,但它似乎工作正常,并提供进展):

  using System; 
using System.Collections.Generic;
使用System.IO;
使用System.Text;
$ b命名空间LoopCopy
{
class程序
{
static void Main(string [] args)
{
if
Console.WriteLine(
用法:LoopCopy.exe SourceFile DestFile);
return;
}

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

FileInfo sourceFile = new FileInfo(srcName);
if(!sourceFile.Exists)
{
Console.WriteLine(源文件{0}不存在,
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:);
使用(FileStream sourceStream =
新的FileStream(srcName,FileMode.Open))
{
使用(FileStream destStream =
新的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;




$ b(int i = 0; i< msg.Length; i ++)
{
Console.Write(\b \b);
}
Console.WriteLine(100%);
Console.WriteLine(完成);
}
}
}


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.

Here is the error that you get:

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

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

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

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.

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

解决方案

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):

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

这篇关于如何在没有CopyFile或CopyFileEx的情况下在Windows上复制大文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆