Je souhaite placer des données compressées dans un référentiel distant.
Pour mettre des données sur ce référentiel, je ne peux utiliser qu'une méthode qui prend le nom de la ressource et son contenu sous la forme d'une chaîne. (comme data.txt + "Bonjour tout le monde").
Le référentiel moque un système de fichiers mais ne l'est pas, donc je ne peux pas utiliser directement le fichier.java: comment obtenir une représentation sous forme de chaîne d'un tableau d'octets compressé?
Je veux être en mesure de faire ce qui suit:
- client envoie au serveur un fichier 'donnees.txt
- compress serveur' donnees.txt dans un fichier compressé « data.zip »
- serveur envoie une représentation de chaîne de data.zip au dépôt
- data.zip magasin de dépôt
- télécharger le client du référentiel data.zip et son pouvoir l'ouvrir avec son outil zip préféré
Le problème se pose à l'étape 3 lorsque j'essaie d'obtenir une représentation sous forme de chaîne de mon fichier compressé.
Voici une classe d'exemple, utilisant le flux zip * et qui émule le référentiel présentant mon problème.
Le fichier zip créé fonctionne, mais après sa 'sérialisation' il est corrompu.
(l'exemple de classe utilise jakarta commons.io)
Un grand merci pour votre aide.
package zip;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import org.apache.commons.io.FileUtils;
/**
* Date: May 19, 2010 - 6:13:07 PM
*
* @author Guillaume AME.
*/
public class ZipMe {
public static void addOrUpdate(File zipFile, File ... files) throws IOException {
File tempFile = File.createTempFile(zipFile.getName(), null);
// delete it, otherwise you cannot rename your existing zip to it.
tempFile.delete();
boolean renameOk = zipFile.renameTo(tempFile);
if (!renameOk) {
throw new RuntimeException("could not rename the file " + zipFile.getAbsolutePath() + " to " + tempFile.getAbsolutePath());
}
byte[] buf = new byte[1024];
ZipInputStream zin = new ZipInputStream(new FileInputStream(tempFile));
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile));
ZipEntry entry = zin.getNextEntry();
while (entry != null) {
String name = entry.getName();
boolean notInFiles = true;
for (File f : files) {
if (f.getName().equals(name)) {
notInFiles = false;
break;
}
}
if (notInFiles) {
// Add ZIP entry to output stream.
out.putNextEntry(new ZipEntry(name));
// Transfer bytes from the ZIP file to the output file
int len;
while ((len = zin.read(buf)) > 0) {
out.write(buf, 0, len);
}
}
entry = zin.getNextEntry();
}
// Close the streams
zin.close();
// Compress the files
if (files != null) {
for (File file : files) {
InputStream in = new FileInputStream(file);
// Add ZIP entry to output stream.
out.putNextEntry(new ZipEntry(file.getName()));
// Transfer bytes from the file to the ZIP file
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
// Complete the entry
out.closeEntry();
in.close();
}
// Complete the ZIP file
}
tempFile.delete();
out.close();
}
public static void main(String[] args) throws IOException {
final String zipArchivePath = "c:/temp/archive.zip";
final String tempFilePath = "c:/temp/data.txt";
final String resultZipFile = "c:/temp/resultingArchive.zip";
File zipArchive = new File(zipArchivePath);
FileUtils.touch(zipArchive);
File tempFile = new File(tempFilePath);
FileUtils.writeStringToFile(tempFile, "hello world");
addOrUpdate(zipArchive, tempFile);
//archive.zip exists and contains a compressed data.txt that can be read using winrar
//now simulate writing of the zip into a in memory cache
String archiveText = FileUtils.readFileToString(zipArchive);
FileUtils.writeStringToFile(new File(resultZipFile), archiveText);
//resultingArchive.zip exists, contains a compressed data.txt, but it can not
//be read using winrar: CRC failed in data.txt. The file is corrupt
}
}
Je souscris. Lorsque vous transmettez des données binaires, vous devez utiliser Byte, pas Char ou String, qui sont UTF16. –
@Marcus Vous voulez dire UTF-8 (vérifier les accessoires sys). Pour ce travail, vous devrez charger le contenu entier du fichier sous la forme d'un tableau d'octets avant de le convertir en une chaîne. Chaque fois que vous encoder/décoder des octets vers/depuis des chaînes, il existe un risque que les caractères (pouvant traverser plusieurs octets) puissent être codés/décodés de manière incorrecte si un tampon est utilisé. –
@Raymond, merci. Je n'étais probablement pas clair. String et Char sont UTF16 (multi-octets). Les octets sont, évidemment, un seul octet, et c'est ce que vous voulez. –