2008-09-07 7 views
6

Кто-нибудь знает способ копирования файла из пути A в путь B и подавления кеша файловой системы Windows?
Типичное использование - копирование большого файла с USB-накопителя или сервера на локальный компьютер. Кажется, что Windows заменяет все, если файл действительно большой, например. 2GiB. Предпочитаете пример на C#, но я предполагаю, что это будет вызов Win32, если это возможно.Скопировать файл без использования кеша окон

+1

Если вы действительно хотите понять механику взаимодействия кеша с копированием файлов, [это обязательное чтение.] (Http://blogs.technet.com/markrussinovich/archive/2008/02/04/2826167.aspx) – 2008-09-07 20:21:06

ответ

5

Еще важнее то, что существуют FILE_FLAG_WRITE_THROUGH и FILE_FLAG_NO_BUFFERING.

MSDN есть хорошая статья на них обоих: http://support.microsoft.com/kb/99794

+0

Этот ответ, хотя правильный, не является ответом на исходный вопрос. Может ли кто-то с правами редактирования переписать его? – 2008-09-08 00:23:00

4

Я не уверен, если это поможет, но взгляните на Increased Performance Using FILE_FLAG_SEQUENTIAL_SCAN.

РЕЗЮМЕ

Существует флаг для CreateFile() называется FILE_FLAG_SEQUENTIAL_SCAN, который направит диспетчера кэша для доступа файл последовательно.

Любой, кто читает потенциально большие файлы с последовательным доступом, может указывать этот флаг для повышения производительности. Этот флаг полезен, если вы читаете файлов, которые являются «в основном» последовательными, , но вы иногда пропускаете небольшие диапазоны байтов.

+0

Я использую этот флаг для тех же целей, и я могу засвидетельствовать, что FILE_FLAG_SEQUENTIAL_SCAN выполняет эту работу. – tzot 2008-10-11 23:24:11

3

Если вы не возражаете, используя инструмент, ESEUTIL работал большой для меня.

Вы можете проверить эту запись blog, сравнивая функции буферизованного и небуферизованного ввода-вывода и откуда получить ESEUTIL.

копируя текст из блога Technet:

Так, глядя на определение буферном I/O выше, мы можем увидеть, где предполагаемые проблемы производительности лежат - в накладных кэш файловой системы. Небуферизованный ввод-вывод (или необработанная копия файла) предпочтительнее при попытке скопировать большой файл из одного места в другое, когда мы не намерены обращаться к исходному файлу после завершения копирования. Это позволит избежать накладных расходов на кеш файловой системы и не позволяет эффективно кэшировать кеш файловой системы большими файловыми данными. Многие приложения выполняют это, вызывая CreateFile() для создания пустого файла назначения, а затем используя функции ReadFile() и WriteFile() для передачи данных. CreateFile() - Функция CreateFile создает или открывает файл, файловый поток, каталог, физический диск, том, буфер консоли, стример, ресурс связи, почтовый ящик или именованный канал. Функция возвращает дескриптор, который можно использовать для доступа к объекту. ReadFile() - Функция ReadFile считывает данные из файла и начинается с позиции, указанной указателем файла. Вы можете использовать эту функцию для синхронных и асинхронных операций. WriteFile() - Функция WriteFile записывает данные в файл в позиции, указанной указателем файла. Эта функция предназначена для синхронной и асинхронной работы. Для копирования файлов по сети, которые являются очень большими, моя полезная утилита копирования - это ESEUTIL, которая является одной из утилит базы данных, поставляемой с Exchange.

6

В C# я нашел что-то вроде этого, чтобы работать, это может быть изменено, чтобы скопировать непосредственно в файл назначения:

public static byte[] ReadAllBytesUnbuffered(string filePath) 
    { 
     const FileOptions FileFlagNoBuffering = (FileOptions)0x20000000; 
     var fileInfo = new FileInfo(filePath); 
     long fileLength = fileInfo.Length; 
     int bufferSize = (int)Math.Min(fileLength, int.MaxValue/2); 
     bufferSize += ((bufferSize + 1023) & ~1023) - bufferSize; 
     using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None, 
              bufferSize, FileFlagNoBuffering | FileOptions.SequentialScan)) 
     { 
      long length = stream.Length; 
      if (length > 0x7fffffffL) 
      { 
       throw new IOException("File too long over 2GB"); 
      } 
      int offset = 0; 
      int count = (int)length; 
      var buffer = new byte[count]; 
      while (count > 0) 
      { 
       int bytesRead = stream.Read(buffer, offset, count); 
       if (bytesRead == 0) 
       { 
        throw new EndOfStreamException("Read beyond end of file EOF"); 
       } 
       offset += bytesRead; 
       count -= bytesRead; 
      } 
      return buffer; 
     } 
    } 
1

Eseutil является правильным ответом, также так Win7/2008 R2, вы можете использовать переключатель/j в Xcopy, который имеет тот же эффект.