Translate this page now :



»Programação
»Programação.NET
»Banco de Dados
»Webdesign
»Office
» Certificações Microsoft 4
»Treinamentos4
»Programação 4
»Webdesign«
»Office & User Tips«
»Grupos de Usuários
»Células Acadêmicas«

Inside
Você já está cadastrado e participa do grupo de usuários de sua cidade ? Se não, comente o porque.
 
 
Faça um pequeno teste com 10 questões de VB
.:.
Teste seus conhecimentos em Visual Basic, SQL Server e ASP 3.0 com nossas provas on-line
.:.
Aprimore seus conhecimentos em programação com nosso treinamento on-line de lógica de programação
.:.
Veja nosso calendário de treinamentos
Gostou da Página?
Então

para um amigo!
 





Por Dennes Torres
dennes@bufaloinfo.com.br
Dennes Torres possui as certificações MCAD, MCSD,MCSE, MCDBA e MCT. Atualmente atua Como diretor da Búfalo Informática, líder do grupo de usuários DevASPNet no Rio de Janeiro e membro da liderança dos grupos getWindows e devSQL, também do Rio de Janeiro, podendo sempre ser encontrado na lista de discussão do grupo DevASPNet (devaspnet-subscribe@yahoogrupos.com.br) bem como nas reuniões do grupo. Mantém dois blogs em http://cidadaocarioca.blogspot.com

Compactando dados com o Framework 2.0

Pesquisa personalizada
Pesquisar Dicas:






Entre as inúmeras novidades do Framework 2.0 esta é mais uma que chama a atenção : Temos uma classe chamada gzipStream que nos permite fazermos compactação e descompatação de arquivos.

Para demonstrar o funcionamento desta classe vou então criar uma pequena aplicação windows para compactar e descompactar arquivos, enfim, um pequeno compactador.

Vou considerar que esse compactador funcionará da seguinte forma :

- Tendo um atalho na pasta sendTo, bastará clicar com o botão direito sobre o arquivo que se deseja compactar e "enviar" o arquivo para o compactador.

- Tendo feito vínculo com uma extensão própria (usarei a extensão .gz), bastará dar duplo clique sobre um arquivo .gz para gerar a descompactação.

A aplicação reconhecerá a tarefa que está sendo realizada através de parâmetros de linha de comando que serão passados pelos atalhos ou diretamente pela linha de comando quando o usuário assim desejar.

Nossa aplicação então irá iniciar-se com uma sub Main criada por nós, para desta forma poder testar facilmente os parâmetros recebidos e decidir o que será feito.

A aplicação aceitará os seguintes parâmetros :

-d <arquivo> : Descompactar esse arquivo
-c <arquivo> : Compactar esse arquivo
-o <arquivo> : Nome do arquivo destino gerado (tanto compactação como descompactação)

Os parâmetros -c e -d não poderão ser utilizados em conjunto.

Vamos então começar a montar a sub Main para fazer o reconhecimento destes parâmetros. Após tratar esses parâmetros precisaremos gerar 3 informações : Arquivo origem, arquivo destino e tarefa a ser realizada.

Depois de criar uma nova WindosApplication e adicionar um novo modulo, vamos iniciar a sub main com o seguinte códiog :

    1 Module Module1

    2     Public Enum eTarefa

    3         Compactar = 0

    4         Descompactar = 1

    5     End Enum

    6 

    7     Public Sub main()

    8         Dim arquivo As String = String.Empty

    9         Dim arquivoDestino As String = String.Empty

   10         Dim tarefa As eTarefa

   11         Dim s As String

   12         Dim i As Integer

O próximo passo será fazer um loop na coleção de argumentos que foram passados via linha de commando. Então podemos observar a facilidade que nos é trazida pelo My, que agrega todo tipo de recurso que precisamos : My.Application.CommandLineArguments

   14         For i = 0 To My.Application.CommandLineArgs.Count - 1

   15 

   16             s = My.Application.CommandLineArgs(i)

   17             s = s.ToLower

   18 

   19         Next

Vamos fazer um select case no parâmetro identificado para testar do que se trata :

   21         Select Case s

   22             Case "-c"

   23             Case "-d"

   24             Case "-o"

   25             Case Else

   26                 MsgBox("Parâmetro inválido!")

   27                 Exit Sub

   28         End Select

As operações que serão realizadas neste ponto pelos parâmetros -c e -d são praticamente as mesmas :

- Validar o parâmetro, apenas um pode existir na linha de comando
- Obter o nome do arquivo, que deve estar ao lado
- Conferir se o arquivo existe
- Obter o caminho completo do arquivo (pode ter sido passado caminho relativo)

Assim sendo podemos criar uma sub para fazer isso :

   31     Private Sub TrataParametro(ByVal i As Integer, ByRef arquivo As String)

   32 

   33 

   34         If Not arquivo.Equals(String.Empty) Then

   35             Console.WriteLine("Os parâmetros -c e -d não podem ser utilizados em conjunto")

   36 

   37 

   38             MsgBox("Os parâmetros -c e -d não podem ser utilizados em conjunto")

   39 

   40             Application.Exit()

   41         End If

   42         arquivo = My.Application.CommandLineArgs(i + 1)

   43 

   44         If Not My.Computer.FileSystem.FileExists(arquivo) Then

   45 

   46             Console.WriteLine("O arquivo a compactar não existe !")

   47 

   48             MsgBox("O arquivo a compactar não existe !" & vbCrLf & arquivo)

   49 

   50             Application.Exit()

   51         Else

   52             Dim fi As IO.FileInfo

   53             fi = New IO.FileInfo(arquivo)

   54             arquivo = fi.FullName

   55         End If

   56 

   57     End Sub

Observe como um pequeno e simples uso do ByRef simplifica a programação. Outro truque interessante é o uso do FileInfo. Como o arquivo pode ter sido passado de forma relativa, não podemos contar com sua string apenas, usei o fileInfo para obter o path completo ao arquivo.

Veja como fica o Select case após isso :

   21         Select Case s

   22             Case "-c"

   23                 TrataParametro(i, arquivo)

   24                 i += 1

   25                 tarefa = eTarefa.Compactar

   26             Case "-d"

   27                 TrataParametro(i, arquivo)

   28                 i += 1

   29                 tarefa = eTarefa.Descompactar

   30             Case "-o"

   31             Case Else

   32                 MsgBox("Parâmetro inválido!")

   33                 Exit Sub

   34         End Select

A alteração do valor do contador e a definição da tarefa a serem feitas ficaram fora da sub (a alteração do contado até podia estar lá, mas fiquei com a impressão de que seria "abusar" das funcionalidades daquela sub)

Por fim falta o -o :

- O arquivo não deve existir, se existir deve ser gerado erro

 

   21         Select Case s

   22             Case "-c"

   23                 TrataParametro(i, arquivo)

   24                 i += 1

   25                 tarefa = eTarefa.Compactar

   26             Case "-d"

   27                 TrataParametro(i, arquivo)

   28                 i += 1

   29                 tarefa = eTarefa.Descompactar

   30             Case "-o"

   31                 arquivoDestino = My.Application.CommandLineArgs(i + 1)

   32 

   33                 If My.Computer.FileSystem.FileExists(arquivoDestino) Then

   34 

   35                     Console.WriteLine("Arquivo destino já existe, não será sobrescrito!")

   36 

   37                     MsgBox("Arquivo destino já existe, não será sobrescrito!")

   38 

   39                     Exit Sub

   40                 End If

   41                 i += 1

   42 

   43             Case Else

   44                 MsgBox("Parâmetro inválido!")

   45                 Exit Sub

   46         End Select

Por fim : o parâmetro -o é opcional, pode não estar lá. De qualquer forma, vamos abrir um formulário para confirmar o caminho e nome do arquivo destino.

Veja então como fica o código completo deste módulo com a sub main :

    1 Module Module1

    2 

    3     Public Enum eTarefa

    4         Compactar = 0

    5         Descompactar = 1

    6     End Enum

    7 

    8     Public Sub main()

    9         Dim arquivo As String = String.Empty

   10         Dim arquivoDestino As String = String.Empty

   11         Dim tarefa As eTarefa

   12         Dim s As String

   13         Dim i As Integer

   14 

   15         For i = 0 To My.Application.CommandLineArgs.Count - 1

   16 

   17             s = My.Application.CommandLineArgs(i)

   18             s = s.ToLower

   19             Select Case s

   20                 Case "-c"

   21                     TrataParametro(i, arquivo)

   22                     i += 1

   23                     tarefa = eTarefa.Compactar

   24                 Case "-d"

   25                     TrataParametro(i, arquivo)

   26                     i += 1

   27                     tarefa = eTarefa.Descompactar

   28                 Case "-o"

   29                     arquivoDestino = My.Application.CommandLineArgs(i + 1)

   30 

   31 

   32                     If My.Computer.FileSystem.FileExists(arquivoDestino) Then

   33 

   34 

   35                         Console.WriteLine("Arquivo destino já existe, não será sobrescrito!")

   36 

   37 

   38                         MsgBox("Arquivo destino já existe, não será sobrescrito!")

   39 

   40                         Exit Sub

   41                     End If

   42                     i += 1

   43                 Case Else

   44                     MsgBox("Parâmetro inválido!")

   45                     Exit Sub

   46             End Select

   47         Next

   48 

   49 

   50         Dim frm As New frmNovoArquivo

   51         frm.Tarefa = tarefa

   52         frm.ArquivoDestino = arquivoDestino

   53         frm.Arquivo = arquivo

   54         Application.Run(frm)

   55     End Sub

   56 

   57     Private Sub TrataParametro(ByVal i As Integer, ByRef arquivo As String)

   58 

   59         If Not arquivo.Equals(String.Empty) Then

   60 

   61             Console.WriteLine("Os parâmetros -c e -d não podem ser utilizados em conjunto")

   62 

   63 

   64             MsgBox("Os parâmetros -c e -d não podem ser utilizados em conjunto")

   65 

   66 

   67             Application.Exit()

   68         End If

   69         arquivo = My.Application.CommandLineArgs(i + 1)

   70 

   71         If Not My.Computer.FileSystem.FileExists(arquivo) Then

   72 

   73             Console.WriteLine("O arquivo a compactar não existe !")

   74 

   75             MsgBox("O arquivo a compactar não existe !" & vbCrLf & arquivo)

   76 

   77             Application.Exit()

   78         Else

   79             Dim fi As IO.FileInfo

   80             fi = New IO.FileInfo(arquivo)

   81             arquivo = fi.FullName

   82         End If

   83 

   84     End Sub

   85 End Module

Vamos então montar o formulário que vai consultar o usuário sobre o nome do arquivo novo a ser gerado. Vou chamar esse formulário de frmNovoArquivo.

Para consultar o usuário sobre a pasta na qual o novo arquivo deverá ser guardado, vamos utilizar o componente FolderBrowserDialog que encontra-se na toolbox.

Veja outras características deste formulário :

- Terá 3 botões : Criar e cancelar, na parte inferior do formulário, e selecionar, ao lado de um label com o nome da pasta de destino, para o usuário trocar a pasta

- Terá um label com o nome da pasta de destino. Devemos definir o auto-size para False para que o label faça o wrap do caminho da pasta

- Terá uma textbox para conter o nome do novo arquivo

- O botão "Criar" deverá aparecer desabilitado e só ser habilitado quando tanto a textbox como o label estiverem preenchidos, formando o caminho e nome completo do arquivo destino.

Vejamos um pouco melhor o código deste form. Na Sub Main passamos para este form alguns valores de propriedades, para que este form possa fazer o trabalho dele : Arquivo de origem, arquivo novo e tarefa. Então precisaremos destas propriedades em nosso novo form :

   46     Dim vArqDestino As String = String.Empty

   47     Dim vArquivo As String = String.Empty

   48     Dim vTarefa As eTarefa

   49 

   50     Friend Property Tarefa() As eTarefa

   51         Get

   52             Return (vTarefa)

   53         End Get

   54         Set(ByVal value As eTarefa)

   55             vTarefa = value

   56         End Set

   57     End Property

   58 

   59 

   60     Public Property Arquivo() As String

   61         Get

   62             Return (vArquivo)

   63         End Get

   64         Set(ByVal value As String)

   65             vArquivo = value

   66         End Set

   67     End Property

   68 

   69     Public Property ArquivoDestino() As String

   70         Get

   71             Return (vArqDestino)

   72         End Get

   73         Set(ByVal value As String)

   74             vArqDestino = value

   75         End Set

   76     End Property

 

Para controlar o botão criar, que deverá ser habilitado e desabilitado conforme o preenchimento desta janela, vamos utilizar o evento textChanged da caixa e criar também uma sub. Veja como fica :

   80     Private Sub txtArquivo_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtArquivo.TextChanged

   81 

   82 

   83         HabilitarBotao()

   84     End Sub

   85 

   86     Private Sub HabilitarBotao()

   87         cmdCriar.Enabled = txtArquivo.Text.Trim <> "" And lblPasta.Text <> ""

   88 

   89 

   90     End Sub

Temos nesta sub um truque de lógica interessante. Quanto a criação da sub, precisaremos chama-la em outros locais, tal como no Load.

No form_load precisaremos analisar os dados recebidos da Main e decidir o que fazer. Se a propriedade ArquivoDestino estiver preenchida, então devemos preencher o label e a caixa de texto com os dados desta propriedade. Porém se a propriedade ArquivoDestino não estiver preenchida deveremos então montar uma sugestão de arquivo destino.

Feito isso chamamos a sub HabilitarBotao, que vai analisar se tudo está preenchido de forma a permitir que o "Criar" fique ativo. Veja como fica o código :

 

   93     Private Sub frmNovoArquivo_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

   94 

   95 

   96         If Not ArquivoDestino.Equals(String.Empty) Then

   97 

   98             txtArquivo.Text = IO.Path.GetFileName(ArquivoDestino)

   99 

  100             lblPasta.Text = IO.Path.GetFullPath(ArquivoDestino)

  101 

  102         Else

  103             txtArquivo.Text = IO.Path.GetFileNameWithoutExtension(Arquivo) & ".gz"

  104 

  105 

  106             lblPasta.Text = IO.Path.GetFullPath(Arquivo)

  107 

  108 

  109             SelecionarPasta()

  110         End If

  111         HabilitarBotao()

  112     End Sub

 

Temos ainda os botões adicionais, "Selecionar", para fazer a seleção de uma nova pasta e "cancelar", para desistir do processamento, veja :

 

  115     Private Sub cmdCancelar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdCancelar.Click

  116 

  117 

  118         Me.Close()

  119     End Sub

  120 

  121     Private Sub cmdSelecionar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdSelecionar.Click

  122 

  123 

  124         SelecionarPasta()

  125     End Sub

  126 

  127     Private Sub SelecionarPasta()

  128         FBD.SelectedPath = lblPasta.Text

  129         FBD.ShowDialog()

  130         If FBD.SelectedPath <> "" Then

  131             lblPasta.Text = FBD.SelectedPath

  132         End If

  133     End Sub

 

A sub selecionarPasta, como devem ter observado, é chamada também do Load.

 

 

Por fim, o botão criar irá fazer a tarefa principal, compactar ou descompactar as informações. Para codificarmos isso precisamos entender melhor como funciona o GZipStream.

O GZipStream utiliza um outro stream qualquer como base, BaseStream, como fica sendo chamado. O que este outro Stream fará depende da configuração do GZipStream.

Se o GZipStream for configurado para compactar, poderemos utilizar os métodos de gravação no GZipStream. Este irá compactar os dados e gravar no baseStream já de forma compactada.

Porém se o GZipStream for configurado para descompactar, ele entende que o BaseStream é um arquivo já compactado e se dispõe a fazer a descompactação. Desta forma o GZipStream fica somente para leitura e a gravação do resultado, descompactado, fica sendo nossa obrigação.

Então vamos começar a analisar como fica o código do botão "Criar". Vamos começar definindo o GZipStream e definindo dois outros Stream : Um para o arquivo de origem e um para o arquivo destino.

 

  136     Private Sub cmdCriar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdCriar.Click

  137 

  138 

  139         Dim fs As IO.FileStream

  140         Dim gz As GZipStream

  141 

  142         ArquivoDestino = IO.Path.Combine(lblPasta.Text, txtArquivo.Text)

  143 

  144         Dim fsOutput As New IO.FileStream(ArquivoDestino, IO.FileMode.Create)

  145 

  146         fs = New IO.FileStream(Arquivo, IO.FileMode.Open)

 

O que vem em seguida depende da tarefa a ser realizada, compactação ou descompactação. Então :

 

  148         If Tarefa = eTarefa.Compactar Then

  149 

  150         Else

  151 

  152         End If

 

No caso da compactação :

 

  148         If Tarefa = e Tarefa.Compactar Then

  149             Dim buffer(fs.Length - 1) As Byte

  150             fs.Read(buffer, 0, buffer.Length)

  151             fs.Close()

  152             gz = New GZipStream(fsOutput, CompressionMode.Compress)

  153 

  154             gz.Write(buffer, 0, buffer.Length)

  155             gz.Close()

  156         Else

 

Já para descompactar a sequencia será um pouco diferente :

- Criamos o GZipStream sendo o BaseStream o arquivo de origem
- Fazemos um laço para ler o conteúdo do GZipStream, passando este conteúdo para um array de bytes. O processo de leitura já estará causando a descompactação
- Gravamos o array de bytes no arquivo de destino

 

  156         Else

  157             Dim buffer() As Byte = New Byte() {}

  158             gz = New GZipStream(fs, CompressionMode.Decompress)

  159 

  160             Dim ret As Integer

  161             Dim pos As Integer = 0

  162             Do

  163                 ReDim Preserve buffer(buffer.Length + 100)

  164 

  165                 ret = gz.Read(buffer, pos, 100)

  166                 pos += 100

  167             Loop While ret = 100

  168 

  169             ReDim Preserve buffer(pos)

  170             fsOutput.Write(buffer, 0, buffer.Length)

  171 

  172             fsOutput.Close()

  173             gz.Close()

  174         End If

Para esta aplicação de compatação é interessante criarmos uma aplicação de setup para configura-la na máquina dos usuários. O ideal é que o usuário não precise chamar a aplicação diretamente, que ele possa clicar com um botão direito sobre um arquivo e através do menu sendTo gerar a compactação. Já a descompatação pode ser feita diretamente nos arquivos .GZ, clicando com o botão direito.

Para fazer isso precisaremos que a aplicação de setup faça duas coisas, além da instalação básica da aplicação :

Então, para começar :

Para adicionar o atalho na pasta SendTo :

 


Para criar o vínculo com a extensão .GZ :

 

Pronto, com isso já pode compilar a solução e instala-la, testando o compactador. Fica como desafio para vocês criar um compactador que permita inserir diversos arquivos compactados em um único arquivo .GZ



Envie seus comentários sobre este artigo

Nome :

E-mail :

Comentários :


Avise-me quando houverem novos comentários nesta página

Veja abaixo os comentários já enviados :

Nome : Jessé E-Mail : friendlira@yahoo.com.br
O bicho !!!
Matéria bastante elucidativa. Valeu !!!