Java : créer une archive Zip en mémoire avec ZipOutputStream

Posté par seiyar81 le 3 avril 2014 | Laisser un commentaire (0)

Une petite class utilitaire pour générer des archives Zip en mémoire, sans rien écrire sur le disque, le tout aussi bien à partir de fichiers physiques ou de texte brut.

package fr.yriase.tools;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.ServletOutputStream;

public class ZipFileWriter {

  /**
  * Flux de l'archive zip
  */
  private ZipOutputStream zos;
  
  /**
  * Constructor: creation d'une nouvelle archive directement dans le stream passé en paramètre
  * @param OutputStream out
  * @throws FileNotFoundException
  */
  public ZipFileWriter(OutputStream out) throws FileNotFoundException {
  	this.zos = new ZipOutputStream(out);
  }
  
  public ZipOutputStream getOutputStream()
  {
  	return this.zos;
  }
  
  /**
  * Ajouter un fichier depuis le disque dur au zip
  * @param String fileName
  * @throws FileNotFoundException
  * @throws IOException
  */
  public void addFile(String fileName) throws FileNotFoundException, IOException {
    FileInputStream fis = new FileInputStream(fileName);
    int size = 0;
    byte[] buffer = new byte[1024];
    
    //Ajouter une entree à l'archive zip
    File file = new File(fileName);
    ZipEntry zipEntry = new ZipEntry(file.getName());
    this.zos.putNextEntry(zipEntry);
    
    //copier et compresser les données
    while ((size = fis.read(buffer, 0, buffer.length)) > 0) {
    	this.zos.write(buffer, 0, size);
  	}
  
  	this.zos.closeEntry();
  	fis.close();
  }
  
  /**
  * Ajouter un fichier depuis un array de bytes au zip
	* @param 
  * @param fileName
  * @throws IOException
  */
  public void addFile(byte[] bytes, String fileName) throws IOException {
    //Ajouter une entree à l'archive zip
    ZipEntry zipEntry = new ZipEntry(fileName);
    this.zos.putNextEntry(zipEntry);
    
    //Copier et compresser les données
    this.zos.write(bytes, 0, bytes.length);
    
    this.zos.closeEntry();
  }
  
  /**
  * Fermer le fichier zip
  * @throws IOException
  */
  public void close() throws IOException {
  	this.zos.finish();
  	this.zos.close();
  }
}

A utiliser comme ceci dans une action Struts par exemple :

public class DownloadZipAction extends Action {

	public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
	
		ServletOutputStream out = response.getOutputStream();

		response.setHeader("Content-Type","application/zip");
		response.setHeader("Content-Disposition", "attachment; filename=\"test.zip\"");

		ZipFileWriter zip = new ZipFileWriter(out);

		zip.addFile("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>var1</test>", "test.xml");
		zip.addFile("C:/test.xml");
		
		zip.close();

	}

}

A garder sous le coude, ça peut toujours servir.

Catégorie: Développement Web, Java | Laisser un commentaire (0)

Java : sérialisation personnalisée de ses objets en JSON avec Flexjson

Posté par seiyar81 le 16 janvier 2014 | Laisser un commentaire (0)
JSON - Flexjson

Si vous travaillez sur des applis Web et Java et que vous vous retrouvez à devoir sérialiser vos données en JSON, il y a de fortes chances pour que vous utilisiez la bibliothèque Flexjson.

Les fonctionnalités de sérialisation sont puissantes et permettent par exemple de sériliaser un objet en profondeur.

Un exemple plutôt simple :


public class Yriase {
	
	private String name;

	public Yriase {
	}

	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}

}


public static void main(String[] args) {

	Yriase y = new Yriase();
	y.setName( "yriase" );

	System.out.println( new JSONSerializer().exclude("*.class").serialize(yriase) );

}

Devrait vous renvoyer la chaîne suivante :

{
	name: "yriase"
}

Imaginons maintenant un cas un peu plus complexe. Vous avez créé une classe, et vous vous attendez à ce que les objets soient formattés d’une façon bien définie.
Pas de chance vous tombez dans le cas où le formattage par défaut de Flexjson ne vous convient pas.

Aucun problème, la bibliothèque vous offre la possibilité de définir vos propres Transformer pour vos données.

Prenons la classe template suivante :


public class Pair<String, Integer> {
	private String key;
	private Integer value;
    
	public Pair() {
	}
    
	public Pair(String k, Integer v) {
		this.key = k;
		this.value = v;
	}
    
	public String getKey() {
		return key;
	}
	public void setKey(String key) {
		this.key = key;
	}
	public Integer getValue() {
		return value;
	}
	public void setValue(Integer value) {
		this.value = value;
	}
}

Le formattage par défaut donnera ceci :

{
	key: "keyname",
	value: 10
}

Or on préfèrerait avoir le formattage suivant :

[ "keyname", 10 ]

Et bien il suffit d’implémenter une classe qui étends AbstractTransformer.
Voici donc la solution au problème :


public class PairTransformer extends AbstractTransformer {
	
	@Override
	public void transform(Object object) {
		Pair<String, Integer> p = (Pair<String, Integer>) object;
		
		getContext().writeOpenArray();
		
		getContext().writeQuoted( p.getKey());
		
		getContext().writeComma();
		
		getContext().write( String.valueOf(p.getValue()) );
		
		getContext().writeCloseArray();
	}
	
}

Et pour terminer il nous faut précisier lors de la sérialisation que l’on a un Transformer customisé :


JSONSerializer serializer = new JSONSerializer();
serializer.transform(new PairTransformer(), 	new Pair<String,Integer>().getClass());

Le tour est joué !

Catégorie: Développement Web, Java | Laisser un commentaire (0)