Pergunta

Estou criando um aplicativo de download e eu desejo para a sala preallocate no disco rígido para os arquivos antes de serem realmente baixado como eles poderiam potencialmente ser bastante grande, e ninguém gosta de ver "Esta unidade está cheia, exclua alguns arquivos e tente novamente." Assim, em que a luz, eu escrevi isso.

// Quick, and very dirty
System.IO.File.WriteAllBytes(filename, new byte[f.Length]);

Ele funciona, pelo menos até que você baixar um arquivo que é várias centenas de MB de, ou potencialmente ainda GB de e você joga o Windows em um frenesi surra se não totalmente acabar com o arquivo de paginação e matar sua memória sistemas completamente. Opa.

Assim, com um pouco mais iluminação, parti com o seguinte algoritmo.

using (FileStream outFile = System.IO.File.Create(filename))
{
    // 4194304 = 4MB; loops from 1 block in so that we leave the loop one 
    // block short
    byte[] buff = new byte[4194304];
    for (int i = buff.Length; i < f.Length; i += buff.Length)
    {
        outFile.Write(buff, 0, buff.Length);
    }
    outFile.Write(buff, 0, f.Length % buff.Length);
}

Isso funciona, assim mesmo, e não sofre do problema de memória incapacitante da última solução. Ainda é lento embora, especialmente em hardware mais antigo, uma vez que escreve (potencialmente vale GB de) dados para o disco.

A questão é esta: Existe uma melhor maneira de realizar a mesma coisa? Existe uma maneira de dizer o Windows para criar um arquivo de tamanho x e simplesmente alocar o espaço no sistema de arquivos em vez de realmente escrever uma tonelada de dados. Eu não me importo sobre inicializar os dados no arquivo em tudo (o protocolo que estou usando - bittorrent - fornece hashes para os arquivos que ele envia, portanto, pior caso para dados uninitialised aleatória é eu recebo uma feliz coincidência e parte do arquivo é correto).

Foi útil?

Solução

FileStream.SetLength é o que você quer . A sintaxe:

public override void SetLength(
    long value
)

Outras dicas

Se você tem que criar o arquivo, eu acho que você provavelmente pode fazer algo como isto:

using (FileStream outFile = System.IO.File.Create(filename))
{
    outFile.Seek(<length_to_write>-1, SeekOrigin.Begin);
    OutFile.WriteByte(0);
}

Onde length_to_write seria o tamanho em bytes do arquivo para gravação. Eu não tenho certeza que eu tenho o C # sintaxe correta (e não em um computador para testar), mas eu tenho feito coisas semelhantes em C ++ no passado e funcionou.

Infelizmente, você não pode realmente fazer isto, basta buscar até o fim. Que irá definir o tamanho do arquivo para algo enorme, mas não pode realmente alocar blocos de disco para armazenamento. Então, quando você vai para gravar o arquivo, ele ainda irá falhar.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top