Come posso copiare un file di grandi dimensioni su Windows senza CopyFile o CopyFileEx?

StackOverflow https://stackoverflow.com/questions/92114

  •  01-07-2019
  •  | 
  •  

Domanda

Esiste una limitazione su Windows Server 2003 che impedisce di copiare file estremamente grandi, in proporzione alla quantità di RAM di cui disponi.La limitazione risiede nelle funzioni CopyFile e CopyFileEx, utilizzate da xcopy, Explorer, Robocopy e dalla classe .NET FileInfo.

Ecco l'errore che ottieni:

Impossibile copiare [nome file]:Esistono risorse di sistema insufficienti per completare il servizio richiesto.

L'è un articolo della base di conoscenza sull'argomento, ma riguarda NT4 e 2000.

C'è anche un suggerimento per utilizzare ESEUTIL da un'installazione di Exchange, ma non ho avuto fortuna nel farlo funzionare.

Qualcuno conosce un modo semplice e veloce per gestire questa situazione?Sto parlando di> 50 Gb su una macchina con 2 Gb di RAM.Ho intenzione di avviare Visual Studio e scrivere qualcosa che lo faccia per me, ma sarebbe bello avere qualcosa che fosse già disponibile, stabile e ben testato.

[Modificare] Ho fornito codice C# funzionante per accompagnare la risposta accettata.

È stato utile?

Soluzione

L'opzione migliore è semplicemente aprire il file originale per la lettura, il file di destinazione per la scrittura e quindi copiarlo in ciclo blocco per blocco.Nello pseudocodice:

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

[Modifica di Richiedente] Ok, ecco come appare in C# (è lento ma sembra funzionare bene e fa progressi):

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

Altri suggerimenti

Se vuoi scrivere codice, un modo per ottimizzare è inviare il file in blocchi (come usando MTOM).Ho utilizzato questo approccio per inviare file di grandi dimensioni da un DataCenter al nostro ufficio per la stampa.

Inoltre, controlla l'utilità TeraCopy menzionata Qui..

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top