org.jopendocument.util.Zip Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jOpenDocument Show documentation
Show all versions of jOpenDocument Show documentation
jOpenDocument is a free library for developers looking to use
Open Document files without OpenOffice.org.
The newest version!
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2008-2013 jOpenDocument, by ILM Informatique. All rights reserved.
*
* The contents of this file are subject to the terms of the GNU
* General Public License Version 3 only ("GPL").
* You may not use this file except in compliance with the License.
* You can obtain a copy of the License at http://www.gnu.org/licenses/gpl-3.0.html
* See the License for the specific language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each file.
*
*/
package org.jopendocument.util;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Set;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipOutputStream;
/**
* Permet d'écrire dans un fichier zip.
*
* @author ILM Informatique
* @see org.jopendocument.util.Unzip
*/
public class Zip {
/**
* Copie de from dans to seulement les entrées dont le nom n'est pas dans
* excludedEntries
.
*
* @param from le zip source.
* @param excludedEntries les noms des entrées à exclure.
* @param to le zip de destination, s'il existe déjà les entrées de from seront ajoutées aux
* existantes.
* @return le fichier zip dest.
* @throws ZipException
* @throws IOException
*/
static public Zip createFrom(File from, File to, Set excludedEntries) throws ZipException, IOException {
Unzip unz = new Unzip(from);
Zip res = new Zip(to);
final Enumeration en = unz.entries();
while (en.hasMoreElements()) {
ZipEntry entry = (ZipEntry) en.nextElement();
if (!excludedEntries.contains(entry.getName())) {
res.zip(entry.getName(), unz.getInputStream(entry));
}
}
unz.close();
return res;
}
/**
* Efface les entrées spécifées de src. Si dest existe, il sera ecrasé.
*
* @param src le zip source.
* @param entriesName les noms des entrées à effacer.
* @param dest le zip de destination.
* @throws ZipException
* @throws IOException
*/
static public void delete(File src, Set entriesName, File dest) throws ZipException, IOException {
if (dest.exists())
dest.delete();
createFrom(src, dest, entriesName).close();
}
// *** Instance
private final OutputStream outstream;
private ZipOutputStream zos;
// is an entry open, ie addEntry() has been called but closeEntry() not yet
private boolean entryOpen;
/**
* Construit un fichier zip. ATTN Le fichier passé sera écrasé lors de la première écriture.
*
* @param f le fichier dans lequel sauver, peut ne pas exister.
* @throws FileNotFoundException if f cannot be written to.
*/
public Zip(File f) throws FileNotFoundException {
this(new FileOutputStream(f));
}
/**
* Construit un fichier zip.
*
* @param out un stream dans lequel écrire.
*/
public Zip(OutputStream out) {
this.outstream = out;
this.zos = null;
this.entryOpen = false;
}
public synchronized void close() throws IOException {
if (this.zos != null) {
// ferme aussi le FileOutputStream
this.zos.close();
}
}
// *** Ecriture
private synchronized ZipOutputStream getOutStream() {
if (this.zos == null) {
this.zos = new ZipOutputStream(this.outstream);
}
return this.zos;
}
/**
* Ajoute newFile dans ce fichier. Il sera enregistré dans le zip directement à la racine.
*
* @param newFile le fichier à ajouter.
* @throws IOException si le fichier ne peut etre zippé.
*/
public void zip(File newFile) throws IOException {
// on ne garde que la derniere partie du chemin
this.zip(newFile.getName(), new BufferedInputStream(new FileInputStream(newFile)));
}
/**
* Zippe le contenu de in
.
*
* @param name le nom de l'entrée.
* @param in l'ajout.
* @throws IOException si in ne peut etre zippé.
*/
public synchronized void zip(String name, InputStream in) throws IOException {
this.putNextEntry(name);
byte b[] = new byte[512];
int len = 0;
while ((len = in.read(b)) != -1) {
this.getOutStream().write(b, 0, len);
}
this.closeEntry();
}
public void zip(String name, byte[] in, final boolean compressed) throws IOException {
// don't make #zip(String, InputStream) call this method, it would require to read the
// entire stream into memory
if (compressed)
this.zip(name, new ByteArrayInputStream(in));
else
this.zipNonCompressed(name, in);
}
/**
* Zip the passed array with the {@link ZipEntry#STORED} method. This method takes care of the
* CRC and size.
*
* @param name the entry name.
* @param in what to zip.
* @throws IOException if an error occurs.
*/
public synchronized void zipNonCompressed(String name, byte[] in) throws IOException {
final ZipEntry entry = new ZipEntry(name);
entry.setMethod(ZipEntry.STORED);
final CRC32 crc = new CRC32();
crc.update(in);
entry.setCrc(crc.getValue());
entry.setSize(in.length);
this.putNextEntry(entry);
this.getOutStream().write(in);
this.closeEntry();
}
/**
* Adds a new entry to this zip file. ATTN you must close the returned stream before you can add
* to this zip again.
*
* @param name the name of the entry.
* @return a stream to write to the entry.
* @throws IOException if a pb occurs.
*/
public synchronized OutputStream createEntry(String name) throws IOException {
this.putNextEntry(name);
return new BufferedOutputStream(this.getOutStream()) {
public void close() throws IOException {
this.flush();
Zip.this.closeEntry();
}
};
}
private final synchronized void putNextEntry(String name) throws IOException, FileNotFoundException {
this.putNextEntry(new ZipEntry(name));
}
private final synchronized void putNextEntry(ZipEntry entry) throws IOException, FileNotFoundException {
if (this.entryOpen)
throw new IllegalStateException("previous entry not closed");
this.entryOpen = true;
this.getOutStream().putNextEntry(entry);
}
protected final synchronized void closeEntry() throws IOException {
this.getOutStream().closeEntry();
this.entryOpen = false;
}
}