Pergunta

Eu usei o código abaixo para arquivos comprimir e eles continuam a crescer em vez de diminuir. I comressed um arquivo de 4 kb e tornou-se 6. Isso é compreensível para um arquivo pequeno devido à sobrecarga de compressão. Eu tentei um arquivo de 400 MB e tornou-se 628 MB após a compressão. O que está errado? Veja o código. (.NET 2.0)

Public Sub Compress(ByVal infile As String, ByVal outfile As String)
    Dim sourceFile As FileStream = File.OpenRead(inFile)
    Dim destFile As FileStream = File.Create(outfile)

    Dim compStream As New GZipStream(destFile, CompressionMode.Compress)

    Dim myByte As Integer = sourceFile.ReadByte()
    While myByte <> -1
        compStream.WriteByte(CType(myByte, Byte))
        myByte = sourceFile.ReadByte()
    End While

    sourceFile.Close()
    destFile.Close()
End Sub
Foi útil?

Solução

Você tem certeza que escrever byte por byte para o fluxo é realmente uma boa idéia? Ele certamente não tem características de desempenho ideais e talvez isso é o que confunde o algoritmo gzip comprimir também.

Além disso, pode acontecer que os dados que você está tentando compressa só não é muito bem-compressível. Se eu fosse você eu iria tentar o seu código com um documento de texto do mesmo tamanho como documentos de texto tendem a comprimir muito melhor do que binária aleatória.

Além disso, você pode tentar usar um DeflateStream pura em oposição a um GZipStream como eles usam o mesmo algoritmo de compressão (deflate), a única diferença é que gzip acrescenta alguns dados adicionais (como a verificação de erros), de modo a DeflateStream pode produzir menor resultados.

Meu VB.NET é um pouco enferrujado, então eu prefiro não vou tentar escrever um exemplo de código em VB.NET. Em vez disso, aqui está como você deve fazê-lo em C #, ele deve ser relativamente simples para traduzi-lo para VB.NET para alguém com um pouco de experiência: (ou talvez alguém que é bom em VB.NET poderia editar o meu post e traduzi-lo para VB.NET)

FileStream sourceFile;
GZipStream compStream;

byte[] buffer = new byte[65536];
int bytesRead = 0;
while (bytesRead = sourceFile.Read(buffer, 0, 65536) > 0)
{
     compStream.Write(buffer, 0, bytesRead);
}

Outras dicas

Se o arquivo subjacente é em si altamente imprevisível (já comprimido ou em grande parte aleatório), em seguida, tentar comprimi-lo fará com que o arquivo para se tornar maior.

indo de 400 a 628Mb sons altamente improvável como um factor de expansão uma vez que o algoritmo deflate (utilizado para GZip) tende para um factor de expansão máxima de 0,03% a sobrecarga do cabeçalho GZip deve ser insignificante.

Edit: O 4.0 c # liberação indica que as bibliotecas de compressão foram melhorados para não causar a expansão significativa de dados uncompressable. Isto sugere que eles não estavam a implementar o "retorno à blocos de fluxo de matérias-" mode. Tente usar a biblioteca de SharpZipLib como um teste rápido. Isso deve lhe fornecer perto de desempenho idêntico quando o fluxo é incompressível por deflate. Se ele não considerar a mudança para isso ou aguardando a liberação 4.0 para uma implementação BCL de maior performance. Note-se que a falta de compressão que você está recebendo sugere fortemente que não há nenhum ponto você tentar comprimir ainda de qualquer maneira

Esta é uma conhecida anomalia com o built em GZipStream (E DeflateStream).
Eu posso pensar de duas soluções:

  • usar um compressor alternativo.
  • construir alguma lógica que examina o tamanho da saída "comprimido" e compara com o tamanho da entrada. Se for maior, Chuck a saída e apenas armazenar os dados.

DotNetZip inclui um GZipStream "fixa" com base em um porto gerenciado de zlib. (É preciso abordagem # 1 de cima). O Ionic.Zlib.GZipStream pode substituir o built-in GZipStream em seus aplicativos com uma simples troca de namespace.

Obrigado a todos por boas respostas. Mais cedo nesta Tentei compactar arquivos e um arquivo de texto .wmv. Mudei o código para DeflateStream e parece funcionar agora. Felicidades.

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