Voici un exemple de classe permettant de regrouper plusieurs images dans une archive unique.
L'archive présente la structure suivante :
- Version : 1 byte
- Count : 1 integer
{ offsetStart : 1 integer | length : 1 integer }
# --> cible : { offsetStart : 1 integer | length : 1 integer | type : 1 byte }#
{ filesContent }
- Count : 1 integer
{ offsetStart : 1 integer | length : 1 integer }
# --> cible : { offsetStart : 1 integer | length : 1 integer | type : 1 byte }#
{ filesContent }
Quatre commandes permettent de constituer et manipuler les archives d'images :
- pack
Exemple : pack("/~/imgArcTest", 355);
- unpack
Exemple : unpack("/~/imgArcTest", "Test-355.img", 355);
- unpackAll
Exemple : unpackAll("/~/imgArc/Test", "Test-355.img");
- unpackrange
Exemple : unpackRange("/~/imgArc/Test", "Test-355.img", 200, 225);
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.RandomAccessFile; /** * Concatène des fichers (de type image) dans un fichier archive dont la structure est la suivante : * - Version : 1 byte * - Count : 1 integer * { offsetStart : 1 integer | length : 1 integer } * # --> cible : { offsetStart : 1 integer | length : 1 integer | type : 1 byte }# * { filesContent } * * @author ede */ public class ImageArchive { /** * Numéro de version du format */ private final static byte VERSION=1; /** * Taille du buffer d'écriture (et de lecture) */ private final static int BUFFER_SIZE=40960; /** * Pattern des fichiers lus. * Ex : x-001.png */ public static String ENCODE_PREFIX="x-"; public static int DIGIT_NUMBER=3; public static String ENCODE_SUFIX=".png"; /** * Pattern des fichiers extraits. */ public static String DECODE_PREFIX=ENCODE_PREFIX; public static String DECODE_SUFIX=ENCODE_SUFIX; /** * Package un ensemble d'images dans une archive * * @param path : Chemin d'accès aux fichiers à packager. * @param count : Nombre de fichier à packager. L'index commence à 0. * @param destFilename : Nom du fichier à prendre en compte. * @return Chemin d'accès au fichier packagé */ public static String pack(final String path, final int count, final String destFilename) { FileInputStream fis = null; RandomAccessFile raf = null; byte[] b = new byte[BUFFER_SIZE]; int offsetStart=0; int length=1+4+count*8; int len = -1; String oPath = path+File.separator+destFilename; try { raf = new RandomAccessFile(oPath, "rw"); raf.writeByte(VERSION); raf.writeInt(count); for(int i=0; i<count; i++) { fis = new FileInputStream(path+File.separator+ENCODE_PREFIX+format(i+1,DIGIT_NUMBER)+ENCODE_SUFIX); offsetStart+=length; raf.seek(offsetStart); length=0; while((len = fis.read(b)) >= 0) { raf.write(b,0,len); length+=len; } raf.seek(1+4+i*8); raf.writeInt(offsetStart); raf.writeInt(length); } raf.close(); } catch (IOException e) { e.printStackTrace(); } return oPath; } /** * Extrait les fichiers contenu dans une archive. * * @param path : Chemin d'accès au répertoire contenant le fichier archive source * @param filename : Nom du fichier archive à partir duquel extraire * @return Chemin d'accès au répertoire contenant les fichiers extraits */ public static String unpackAll(final String path, final String filename) { byte version; FileOutputStream fos = null; RandomAccessFile raf = null; int count = 0; byte[] b = new byte[BUFFER_SIZE]; int offsetStart = 0; int length = 0; int num = 0; int mod = 0; File f = null; try { raf = new RandomAccessFile(path+File.separator+filename, "r"); version = raf.readByte(); count = raf.readInt(); for(int i=0; i<count; i++) { raf.seek(1+4+i*8); offsetStart = raf.readInt(); length = raf.readInt(); raf.seek(offsetStart); f = new File(path+File.separator+"unpack"+File.separator+DECODE_PREFIX+format(i,DIGIT_NUMBER)+DECODE_SUFIX); if(f.createNewFile()) { fos = new FileOutputStream(f, true); num = length / BUFFER_SIZE; mod = length % BUFFER_SIZE; for(int j=0; j<num; j++) { raf.read(b); fos.write(b); fos.flush(); } raf.read(b,0,mod); fos.write(b,0,mod); fos.flush(); } } } catch (IOException e) { e.printStackTrace(); } finally { try { if (fos!=null) fos.close(); } catch (IOException e) { e.printStackTrace(); } } return path+File.separator+"unpack"; } /**
* Extrait le fichier contenu dans une archive correspondant à l'index donné.
*
* @param path : Chemin d'accès au répertoire contenant le fichier archive source
* @param filename : Nom du fichier archive à partir duquel extraire
* @param index : index du fichier à extraire. L'index commence à 0.
* @return Chemin d'accès au répertoire contenant les fichiers extraits
*/
public static String unpack(final String path, final String filename, final int index) {
byte version;
FileOutputStream fos = null;
RandomAccessFile raf = null;
byte[] b = new byte[BUFFER_SIZE];
int offsetStart = 0;
int length = 0;
int num = 0;
int mod = 0;
File f = null;
int count = 0;
try {
raf = new RandomAccessFile(path+File.separator+filename, "r");
version = raf.readByte();
count = raf.readInt();
if (index<0 || index>count)
throw new ArrayIndexOutOfBoundsException();
raf.seek(1+4+index*8);
offsetStart = raf.readInt();
length = raf.readInt();
raf.seek(offsetStart);
f = new File(path+File.separator+"unpack"+File.separator+DECODE_PREFIX+format(index,DIGIT_NUMBER)+DECODE_SUFIX);
if(f.createNewFile()) {
fos = new FileOutputStream(f, true);
num = length / BUFFER_SIZE;
mod = length % BUFFER_SIZE;
for(int j=0; j<num; j++) {
raf.read(b);
fos.write(b);
fos.flush();
}
raf.read(b,0,mod);
fos.write(b,0,mod);
fos.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fos!=null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return path+File.separator+"unpack";
}
/**
* Extrait le fichier contenu dans une archive correspondant à l'index donné.
*
* @param path : Chemin d'accès au répertoire contenant le fichier archive source
* @param filename : Nom du fichier archive à partir duquel extraire
* @param index1 : index inférieur de la plage de fichiers à extraire. L'index commence à 0.
* @param index2 : index supérieur de la plage de fichiers à extraire.
* @return Chemin d'accès au répertoire contenant les fichiers extraits
*/
public static String unpackRange(final String path, final String filename, final int index1, final int index2) {
byte version;
FileOutputStream fos = null;
RandomAccessFile raf = null;
int count = 0;
byte[] b = new byte[BUFFER_SIZE];
int offsetStart = 0;
int length = 0;
int num = 0;
int mod = 0;
File f = null;
try {
raf = new RandomAccessFile(path+File.separator+filename, "r");
version = raf.readByte();
count = raf.readInt();
if (index1<0 || index2>count || index1>index2)
throw new ArrayIndexOutOfBoundsException();
for(int i=index1; i<index2; i++) {
raf.seek(1+4+i*8);
offsetStart = raf.readInt();
length = raf.readInt();
raf.seek(offsetStart);
f = new File(path+File.separator+"decode"+File.separator+DECODE_PREFIX+format(i,DIGIT_NUMBER)+DECODE_SUFIX);
if(f.createNewFile()) {
fos = new FileOutputStream(f, true);
num = length / BUFFER_SIZE;
mod = length % BUFFER_SIZE;
for(int j=0; j<num; j++) {
raf.read(b);
fos.write(b);
fos.flush();
}
raf.read(b,0,mod);
fos.write(b,0,mod);
fos.flush();
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fos!=null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return path;
}
/**
* Produit un compteur de fichier formaté de la forme suivante :
* 001, 002, ..., 00N sur 3 digits.
*
* @param num : index à formater
* @param size : nombre de digit à prendre en compte
* @return Compteur formaté
*/
private static String format(int num, int size) {
String str=Integer.toString(num);
while(str.length()<size) {
str = "0"+str;
}
return str;
}
/**
* Méthode de test...
*
* @param args
*/
public static void main(String[] args) {
long t0 = System.currentTimeMillis();
ENCODE_PREFIX = "x-";
ENCODE_SUFIX = ".png";
DECODE_PREFIX = "y-";
//ENCODE_SUFIX = ".png";
if ("-pack".equals(args[0])) {
String path = args[1];
int count = Integer.parseInt(args[2]) ;
pack(path, count, "Test-"+count+".img");
}
if ("-unpackAll".equals(args[0])) {
String path = args[1];
String name = args[2];
unpackAll(path, name);
}
if ("-unpack".equals(args[0])) {
String path = args[1];
String name = args[2];
int count = Integer.parseInt(args[3]) ;
unpack(path, name, count);
}
if ("-unpackRange".equals(args[0])) {
String path = args[1];
String name = args[2];
int index1 = Integer.parseInt(args[3]);
int index2 = Integer.parseInt(args[4]);
unpackRange(path, name, index1, index2);
}
long t1 = System.currentTimeMillis();
System.out.println("--> time="+(t1-t0));
// unpackAll("/~/imgArc/Test", "Test-355.img");
// unpack("/~/imgArcTest", "Test-355.img", 355);
// unpackRange("/~/imgArc/Test", "Test-355.img", 200, 225);
}
}