MSOffice2007 では、docx,xlsx,pptx のように 拡張子に x が追加されているが、この実体は、zip ファイルで中身はXML等で構成されている。 したがって、データファイルだけを展開して中身を書きかえて、再度 zip アーカイブに戻してやれば、MSOffice なしで、内容を操作することができる。
今回はそのためのJavaコード。 このサンプルでは中身の操作は一切しないで、単に既存の sample.pptx ファイルを作業ディレクトリに展開して、その後、result.pptx ファイルにzipアーカイブとして保存しているだけ。
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
public class Test {
private static byte[] buf = new byte[1024];
private static final int EOF=-1;
private void addZipEntry(ZipOutputStream zos,String name,File file) throws Exception {
if(file==null || file.exists()==false){
return ;
}
ZipEntry ent=new ZipEntry(name);
zos.putNextEntry(ent);
BufferedInputStream bin = new BufferedInputStream( new FileInputStream(file) );
int c;
while( (c=bin.read()) != EOF){
zos.write( (byte)c );
}
bin.close();
zos.closeEntry();
}
public void copy(File inZipFile,File outZipFile) throws Exception {
File tmpdir = new File("tmp");
tmpdir.mkdirs();
ZipOutputStream zos=new ZipOutputStream(new FileOutputStream(outZipFile));
ZipFile zf=new ZipFile(inZipFile);
java.util.Enumeration enu=zf.entries();
while(enu.hasMoreElements()){
ZipEntry ze=(ZipEntry)enu.nextElement();
String name=ze.getName();
File f=new File(tmpdir,name);
f.getParentFile().mkdirs();
FileOutputStream fout=new FileOutputStream(f);
BufferedInputStream bin=new BufferedInputStream(zf.getInputStream(ze));
try {
for (;;) {
int len = bin.read(buf);
if (len < 0) break;
fout.write(buf, 0, len);
}
}
finally{
bin.close();
fout.close();
}
addZipEntry(zos,name,f);
}
zf.close();
zos.close();
delete(tmpdir);
}
private static void delete(File f){
if(f.isFile()){
f.delete();
}
if(f.isDirectory()){
File[] files=f.listFiles();
for(int i=0; i<files.length; i++){
delete( files[i] );
}
f.delete();
}
}
public static void main(String[] args) {
Test t = new Test();
try{
File in = new File("sample.pptx");
File out = new File("result.pptx");
t.copy(in,out);
}
catch(Exception ex){
ex.printStackTrace();
}
}
}