Atualização! Compactando e Transmitindo DataSets via XML
Leonel Fraga de Oliveira 31/03/2011 12:53

Ícone de um arquivo ZipOlá meus caros! Esta semana foi muito triste para mim, devido ao falecimento da minha mãe no domingo passado (27/03). Eu ainda estou na fase de superação de tal acontecimento, e graças à força minha família e os meus amigos estão me dando estou superando bem isso. Tem aqueles momentos que bate uma saudade imensa, mas a vida continua, e ela não quer que eu fique tão triste e que eu continue vivendo com alegria.

Bem, dando continuação a essa nova fase da minha vida, recebi o email de um leitor do NM Tech que se interessou pelo método de compactação de DataSets, porém encontrou algumas dificuldades em utilizar o código daquele post com a versão mais nova do Ionic.Zip.

E como estou ocupando minha mente com várias coisas, resolvi pesquisar sobre esse assunto e sim, há diferenças um um tanto significativas caso você use a versão 1.9 da biblioteca de compactação.

Vamos agora tornar a nossa classe EngineCompactacaoDataSet compatível com essa versão? Não vou colocar o corpo da classe, somente os métodos para comentar a diferença entre as versões, belê!

Método de Compactação:

public static byte[] CompactaXML(string XMLACompactar)
{
	byte[] ret = new byte[0];
	using (Ionic.Zip.ZipFile zip = new ZipFile(Encoding.UTF8))
	{
		zip.CompressionLevel = Ionic.Zlib.CompressionLevel.Default;
		MemoryStream sXMLBytes = new MemoryStream(Encoding.UTF8.GetBytes(XMLACompactar));
		
		/*Este trecho de código mudará se você usar a versão 1.9 do Ionic.Zip!*/
		//zip.AddFileStream("data.xml", "xml", sXMLBytes); //Este método não existe mais na versão 1.9!
		zip.AddEntry("xml/data.xml", sXMLBytes); //Agora em vez do AddFileStream, usaremos o AddEntry, informando o caminho completo que o arquivo ficará dentro do zip.
		
		/*Daqui para baixo permanece o mesmo*/
		MemoryStream sZip = new MemoryStream();
		zip.Save(sZip);
		sZip.Position = 0;
		ret = new byte[sZip.Length];
		sZip.Read(ret, 0, ret.Length);
		sZip.Close();
		sZip.Dispose();
		sXMLBytes.Close();
		sXMLBytes.Dispose();
	}
	return ret;
}

Este método tem apenas uma diferença em relação ao do outro post: O método AddFileStream presente na versão anterior não existe nessa nova versão, e foi substituído pelo método AddEntry. Na sobrecarga utilizada aqui, utilizamos uma string que conterá o caminho completo do arquivo dentro do pacote Zip. No nosso caso, colocamos a string “xml/data.xml”, indicando que ele ficará dentro da entrada chamada “data.xml” dentro do diretório “xml”. Como segundo parâmetro, colocamos o Stream que será correspondente a esta entrada no arquivo zip.

Também note que fizemos a referência completa (inclusive com os namespaces) da enumeração CompressionLevel (abaixo da chamada do using que usamos para declarar o arquivo zip), que também mudou em relação ao outro código (antes o valor “Default” era todo em letras maiúsculas).

Método de Descompressão:

public static string DescompactaXML(byte[] XmlCompressed)
{
	string ret = String.Empty;
	using (ZipFile unZip = ZipFile.Read(XmlCompressed))
	{
		MemoryStream ms2 = new MemoryStream();
		//unZip.Extract("xml/data.xml", ms2); //Este método não existe mais na versão 1.9
		
		/*Este trecho de código é compatível com a versão 1.9 do Ionic.Zip: Devemos pegar a entrada desejada na coleção de ZipEntries.*/
		List<ZipEntry> cxmlExtraido = unZip.Entries.ToList<ZipEntry>();
		ZipEntry xmlExtraido = cxmlExtraido[0]; //Como temos somente uma entrada e já sabemos seu conteúdo, podemos acessá-la direto pelo índice.
		xmlExtraido.Extract(ms2);
		
		/*Daqui para baixo permanece o mesmo*/
		byte[] zipE = new byte[ms2.Length];
		ms2.Position = 0;
		ms2.Read(zipE, 0, zipE.Length);
		ret = Encoding.UTF8.GetString(zipE);
		ms2.Close();
		ms2.Dispose();
	}
	return ret;
}

Aqui a coisa já ficou um pouquinho mais complexa. Em vez do método Extract que não existe mais nessa nova versão, devemos acessar a coleção Entries do objeto da classe ZipFile (variável unZip). Esta propriedade Entries é do tipo ICollection<ZipEntry>. Para acessá-la efetivamente, devemos fazer unboxing desta interface ICollection para um List<ZipEntry>. Para tal, criamos a variável cxmlExtraido do tipo List<ZipEntry>, e chamamos o método de extensão ToList<ZipEntry>() da propriedade Entries do arquivo Zip para inicializar esta lista.

Logo após, criamos um objeto do tipo ZipEntry que será a nossa entrada do arquivo Zip, e atribuímos o valor do índice “0” da nossa lista cxmlExtraido. Como sabemos que só vamos ter 1 item nesta lista, podemos fazer essa atribuição direta sem problemas.

Agora sim, iremos extrair esta entrada do arquivo Zip para um Stream utilizado o método Extract do objeto ZipEntry (variável xmlExtraido), que recebe como parâmetro o stream em que o arquivo será colocado.

Este novo código é compatível inclusive com a versão do Ionic.Zip para Compact Framework, que vem junto com o pacote que poderá ser baixado em http://dotnetzip.codeplex.com/

E agora, sim, vou disponibilizar um pequeno exemplo de implementação (ele não compacta um DataSet em si, somente zipando uma string qualquer e recuperando-a; veja o outro post para um exemplo usando DataSets), um em Windows Forms e outro do tipo Smart Device. A solução contém os 2 projetos e foi desenvolvida no Visual Studio 2008 SP1, rodando .NET Framework 3.5 SP1.

Divirtam-se! :)

Exemplo de aplicação dos Métodos de Compactação de String (o XML do DataSet é uma string, né? hehe).

Leonel Fraga de Oliveira Leonel Fraga de Oliveira é formado em Processamento de Dados na Faculdade de Tecnologia de São Paulo (FATEC-SP - 2002) e anteriormente em Técnico em Eletrônica, pela ETE Professor Aprígio Gonzaga (lá em 1999).
Atualmente trabalha como Analista de Sistemas na Prefeitura Municipal de São Caetano do Sul - SP
Tem como hobbies DJing (também trabalha como DJ freelancer) e ciclismo, além da manutenção dos sites NeoMatrix Light e NeoMatrix Tech.
Gosta de música eletrônica, tecnologia, cinema (super fã de Jornada nas Estrelas), gastronomia e outras coisas mais.


Compartilhe nas redes sociais

   

Deixe seu comentário

comments powered by Disqus