Há um blog do MSDN descrevendo por que o Windows se comporta como você descrevê-lo.
Primeiro, vamos mencionar que o que você vê é apenas em NTFS.
Para testar o que você disse, escrevi um pequeno programa que grava 40 kB em um arquivo a cada 5 segundos. O arquivo é mantido aberto entre cada gravação. Um segundo programa usa FindFirstFileEx
para obter o tamanho atual do arquivo. Como terceiro eu uso dir
no cmd.exe. Com essa configuração, posso ver exatamente o que você descreve.
A causa desse problema é uma decisão de design tomada no NTFS. Em NTFS (como no sistema de arquivos Unix), o mesmo arquivo pode estar em dois diretórios - isso é chamado de hardlink. Isso significa que você tem dois diretórios, cada um com uma entrada para o arquivo e você tem o próprio arquivo com suas propriedades. O tamanho do arquivo é uma propriedade que pertence ao arquivo, portanto, ele é armazenado lá. Mas, se alguém quiser uma lista dos arquivos em um diretório com propriedades como o tamanho do arquivo, você terá um desempenho muito baixo se você não tivesse apenas que ler o diretório em si, mas também ler as informações de todos os arquivos. É provável que os dados de um diretório sejam armazenados sequencialmente, mas é provável que os dados de arquivos diferentes estejam espalhados por todo o disco. Portanto, o NTFS armazena uma cópia do tamanho do arquivo na entrada / entradas de diretório.
Você pode ter adivinhado, isso também tem um impacto no desempenho. Pense em 10 hardlinks para o mesmo arquivo. Você deseja que o NTFS atualize 10 entradas de diretório sempre que gravar em um arquivo? Não. Então, uma segunda decisão de projeto foi tomada desde o Vista: os dados na entrada de diretório só são atualizados quando o arquivo é fechado.
Você pode facilmente verificar isso: executar um programa que grava em um arquivo e mantém o arquivo aberto. Execute dir
e você não verá um tamanho atualizado. Ou escreva um arquivo com o Bloco de Notas (que fecha o arquivo no final) e imediatamente o novo tamanho de arquivo é exibido em dir
ou Explorer.
Por que isso F5 ajuda a atualizar o tamanho do arquivo? O Explorer chama GetNamedSecurityInfo que, internamente, abre o arquivo e fecha (você pode verificar isso em SysInternals Process Monitor ). Se eu chamar GetNamedSecurityInfo
no meu próprio programa e, em seguida, chamar FindFirstFileEx
, vejo o novo tamanho de arquivo imediatamente. Assim, o comportamento observado é exatamente o esperado da teoria.
Mas por que você não vê o novo tamanho de arquivo imediatamente no Explorer? Parece que o Explorer está chamando pela primeira vez FindFirstFileEx
e, em seguida, GetNamedSecurityInfo
. Portanto, o Explorer está obtendo o tamanho antigo e, em seguida, aciona a atualização da entrada de diretório. Se você executar dir
no cmd.exe, poderá ver que a entrada de diretório agora possui o novo tamanho de arquivo. É só que o Explorer ainda não sabe disso. O Explorer leva um segundo F5 para obter o tamanho mais recente e, em seguida, aciona novamente uma atualização.
A partir de uma visualização de desenvolvedores de aplicativos, eu não consideraria isso um bug do Explorer - este é um caso especial para um dos sistemas de arquivos suportados, e um aplicativo deve ser abstraído dos sistemas de arquivos. Mas como o Explorer faz parte do Windows, eu penso que a Microsoft poderia ter feito melhor e mudado a ordem das chamadas de função para obter uma melhor experiência do usuário.
BTW, obrigado por essa pergunta muito interessante! Eu gosto de ter aprendido tal NTFS interna.