Como Copiar um Arquivo Sem Usar o Cache de Arquivos do Windows

Quando se trata de gerenciamento de arquivos no Windows, você pode encontrar situações em que o cache de arquivos do sistema pode prejudicar o desempenho—especialmente ao lidar com arquivos grandes. Por exemplo, copiar um arquivo grande de um pen drive ou de um servidor para sua máquina local pode ser problemático, pois o Windows faz o cache do arquivo, o que pode levar à troca de dados e aumentar o tempo necessário para a operação ser concluída.

Neste post do blog, exploraremos como resolver esse problema copiando arquivos sem utilizar o cache do sistema de arquivos do Windows, especificamente usando C#.

Compreendendo o Cache do Sistema de Arquivos do Windows

Antes de mergulhar na solução de código, é importante entender o que é o cache do sistema de arquivos. O Windows usa um cache para acelerar as operações de arquivo, que geralmente envolve:

  • Armazenar dados de arquivos na memória para um acesso mais rápido.
  • Buscar descarregar dados de dispositivos mais lentos, como pen drives, para a memória do sistema mais rápida.

No entanto, com arquivos maiores (pense em 2 GiB ou mais), esse processo de cache pode levar a ineficiências, já que o sistema tenta gerenciar a memória disponível.

A Solução: Usando Chamadas da API Win32

Para contornar esse comportamento de cache, o Windows fornece flags específicas que você pode usar ao trabalhar com operações de arquivo. Essas flags são:

  • FILE_FLAG_WRITE_THROUGH: Essa flag garante que as gravações no arquivo sejam escritas diretamente no dispositivo de armazenamento e não sejam armazenadas em cache na memória.
  • FILE_FLAG_NO_BUFFERING: Essa flag desabilita o cache do sistema para o arquivo, o que significa que todas as operações de leitura e gravação vão diretamente para o disco sem serem armazenadas em cache.

Você pode utilizar essas flags no seu código C# para realizar a cópia direta de arquivos sem usar o cache.

Implementação Passo a Passo em C#

Aqui está como implementar a solução em C#:

  1. Adicione Bibliotecas Necessárias: Certifique-se de incluir os namespaces necessários para operações de arquivo e serviços de interop.

    using System;
    using System.IO;
    using System.Runtime.InteropServices;
    
  2. Declare Métodos Nativos: Você precisa declarar as funções necessárias da API Win32.

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern IntPtr CreateFile(
        string lpFileName,
        uint dwDesiredAccess,
        uint dwShareMode,
        IntPtr lpSecurityAttributes,
        uint dwCreationDisposition,
        uint dwFlagsAndAttributes,
        IntPtr hTemplateFile);
    
    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool ReadFile(
        IntPtr hFile,
        byte[] lpBuffer,
        uint nNumberOfBytesToRead,
        out uint lpNumberOfBytesRead,
        IntPtr lpOverlapped);
    
    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool WriteFile(
        IntPtr hFile,
        byte[] lpBuffer,
        uint nNumberOfBytesToWrite,
        out uint lpNumberOfBytesWritten,
        IntPtr lpOverlapped);
    
    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool CloseHandle(IntPtr hObject);
    
  3. Usando as Flags: Na sua função de cópia de arquivo, use as flags para criar os manipuladores de arquivos.

    public void CopyFileWithoutCache(string sourceFilePath, string destFilePath)
    {
        const uint GENERIC_READ = 0x80000000;
        const uint GENERIC_WRITE = 0x40000000;
        const uint OPEN_EXISTING = 3;
        const uint FILE_FLAG_WRITE_THROUGH = 0x80000000;
        const uint FILE_FLAG_NO_BUFFERING = 0x20000000;
    
        IntPtr sourceHandle = CreateFile(sourceFilePath, GENERIC_READ, 0, IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING, IntPtr.Zero);
        IntPtr destHandle = CreateFile(destFilePath, GENERIC_WRITE, 0, IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING, IntPtr.Zero);
    
        // Implementar lógica de leitura e gravação de arquivo aqui...
    
        CloseHandle(sourceHandle);
        CloseHandle(destHandle);
    }
    

Conclusão

Com os passos descritos acima, você pode copiar arquivos grandes de forma eficiente sem a interferência do cache do sistema de arquivos do Windows. Esse método é particularmente benéfico ao lidar com arquivos de alta capacidade transferidos de dispositivos lentos, como pen drives.

Para mais detalhes, verifique a documentação da Microsoft sobre FILE_FLAG_WRITE_THROUGH e FILE_FLAG_NO_BUFFERING.

Ao entender e aproveitar essas flags, você pode melhorar significativamente o desempenho das suas operações de arquivo. Bom codificação!