Bom dia galera, me deparei com uma tarefa que no início achei simples mas está me dando um pouco de dor de cabeça.
Preciso completar o espaço livre de um disco (Ex. Uma partição de um Pen Drive, uma Partição do HD) mas preciso realizar isso da forma mais rápida possível.
A solução que encontrei foi a seguinte:
Como preciso ocupar o espaço livre de um disco pensei em criar um arquivo do tamanho do espaço livre. Chamo isso de POG mas tudo bem… rsrsrsr
Sendo assim criei essa classe.
public CompletarEspacoLivre(File arquivoDestino, int espacoLivre) throws IOException {
//Recebo como parâmetro do construtor o caminho + o nome do arquivo que será gerado e
// o espaço livre do disco que será usado como base para a criação do arquivo.
Funciona perfeitamente (Aparentemente), no entanto gostaria de saber se esta forma seria a melhor solução para preencher o espaço livre de um disco mantendo uma boa performance.
a) Você só testou seu programa com pendrives pequenos - e os arquivos com mais de 2GB? (Embora, obviamente, se o pendrive estiver formatado como FAT você terá dificuldade de criar um arquivo com mais de 2 GB)?
b) Se o pendrive ou HD estiver formatado como NTFS e ele estiver configurado para comprimir os arquivos, o que irá ocorrer é que mesmo que você saiba o espaço vazio disponível, o código que você escreveu (que preenche o espaço com zeros) irá criar um arquivo que será muito compressível (afinal de contas são apenas zeros binários).
Recomendo usar um programa em C ++ mesmo, que deve ser fácil de achar na Internet. Esses programas costumam gravar dados aleatórios em vez de zeros binários, e os dados aleatórios não são compressíveis, portanto o espaço disponível será integralmente preenchido.
A aplicação final será para Android, sendo assim preencherei o SDCard que no máximo terá 32GB e estará sempre no formato FAT.
Como vai ser para Android tem que ser em JAVA mesmo.
Percebi uma falha aqui no código, o tamanho máximo de alocação de buffer da dalvikvm é de 67108864 bytes sendo assim se o espaço livre for maior que isso vai gerar uma exeption. Sendo assim teria de fazer um laço definindo um buffer constante e repetindo até o espaço ser completamente preenchido.
Não sei se é a única forma de “encher” um disco mas eu pensei nessa possibilidade de criar um arquivo assim como quando baixamos um torrent de por exemplo 5GB onde antes mesmo do arquivo ser baixado o espaço necessário para ele já é previamente alocado no disco.
Nesse caso, em que chamamos seek, o Java na verdade está chamando uma API do Linux que faz exatamente o que você quer (criar um arquivo com o tamanho determinado).
Por motivos de segurança, em vez de simplesmente reservar o espaço, o Linux, quando escrevemos nessa posição 2 bilhões, preenche todas as posições anteriores com zeros.
E esse preenchimento é que demora um monte de tempo. Como não existem arquivos “esparsos” em FAT, o Linux é obrigado a fazer isso (fazer a gravação física).
Estou falando “Linux” porque, como você deve saber, o Android nada mais é que uma distribuição do Linux
Note que se o SDCard fosse formatado com extfs ou outro filesystem típico do Linux (como o JFS, XFS, Reiser etc.), seria criado um arquivo “esparso” (ou seja, posições não escritas não são escritas fisicamente no disco) e o “write” voltaria instantaneamente. Mas como o SDCard é FAT não existem arquivos “esparsos”.
Entendi entanglement, era exatamente o que eu estava procurando.
Cara muito obrigado! Ajudou muito mesmo hoje vou fazer testes usando SDCards classe 6 e 10 para ver analisar a diferença entre os tempos.
Vou tentar formatar o SD com outros sistemas de arquivos como os que você citou abaixo.
Não faça isso - aí você vai ter de gravar um arquivo com dados aleatórios; se você simplesmente criar um arquivo esparso, não vai sobreescrever eventual informação sigilosa que você quer proteger, e se bobear até vai fazer com que o Linux reporte que o espaço não está sendo usado (ou seja, deixe você gravar mais bytes que a capacidade nominal do SD) - queria saber se é por isso que você quer “lotar” o disco. É para sobreescrever o cartão para que ninguém possa “desapagar” os dados já contidos?
Então… Em primeira instância o objetivo encher o cartão sobrescrevendo-o só não entendi a parte do ninguém poder “desapagar” os dados já contidos rsrsrsr
É assim. Digamos que o Linux executasse a sequencia do seu programa Java simplesmente criando um arquivo de 2GB, mas não apagando o que já existia lá.
Você poderia recuperar com facilidade o que já estava escrito dentro do cartão (embora tivesse de juntar os pedaços )