

| com exemplos em VB |
| Componente para deixar forms em Vb semelhantes às telas do winnamp |
| Componente para colocar sua aplicação VB no Systray |
| Componente para transformar sua aplicação VB em serviço |
| Ferramentas úteis para quem usa Olap Server |
| |

![]() |
||||||||
|
|
||||||||
Por Dennes
Torres dennes@bufaloinfo.com.brDennes 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 e http://br.thespoke.net/blogs/dennes/default.aspx |
|
|
|
|
| Compactando dados com o Framework 2.0 | |
|
|
|
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
Veja abaixo os comentários já enviados :
| Nome : Jessé | E-Mail : friendlira@yahoo.com.br |
| O bicho !!! Matéria bastante elucidativa. Valeu !!! |
|