Java – Uses compression to generate corrupted docx

Uses compression to generate corrupted docx… here is a solution to the problem.

Uses compression to generate corrupted docx

First let me say I created an account here because I’ve been banging my head against the wall to try and fix this, so be it.

Also, I’ve seen this issuehere None of these answers helped, I tried them all.

I need to create a word document with a simple table and data. I decided to create a sample document where I got the XML needed to create the document. I moved all folders from the unzipped docx file to my Assets folder. Once I realized I couldn’t write to the Assets folder, I wrote a way to copy all the files and folders to the device’s external storage location and then write the document I created to the same location. From there I tried to compress the file back to a .docx file. This is where things don’t work.

The actual docx file is created and I can move it to my computer via DDMS, but when I look at it, Word says it’s corrupted. What’s so strange about this though, if I unzip it and then recompress it on my computer without making any changes, then it works perfectly. I used a program called DiffMerge (for Mac) to compare the sample unzipped docx file with the unzipped docx file I created, and it says they are exactly the same. So, I think it has something to do with the compression process in Android.

I also tried unzipping the sample docx file on my computer, moving all the files and folders to my Assets folder, including the document.xml file, and then trying to compress it without adding my own document.xml file and using one of the samples, that didn’t work either. Another thing I tried was to put the actual docx file in my Assets folder, unzip it into my external storage, and then recompress it without doing anything. This also failed.

I was basically overwhelmed. Please someone help me with this.

Here is some of my code:

  1. First call moveDocxFoldersFromAssetsToExternalStorage().
  2. After that, all files are called.
  3. I then create the document.xml file and place it in the Word directory to which it belongs
  4. Everything is where it should be, I now try to create a zip file.

.

private boolean moveDocxFoldersFromAssetsToExternalStorage(){
    File rootDir = new File(this.externalPath);
    rootDir.mkdir();

copy("");

 This is to get around a glitch in Android which doesnt list files or folders
     with an underscore at the beginning of the name in the assets folder.
     This renames them once they are saved to the device.
     We need it to show up in the list in order to move them.

File relsDir = new File(this.externalPath + "/word/rels");
    File renameDir = new File(this.externalPath + "/word/_rels");
    relsDir.renameTo(renameDir);

relsDir = new File(this.externalPath + "/rels");
    renameDir = new File(this.externalPath + "/_rels");
    relsDir.renameTo(renameDir);

 This is to get around a glitch in Android which doesnt list hidden files.
     We need it to show up in the list in order to move it.

relsDir = new File(this.externalPath + "/_rels/rels.rename");
    renameDir = new File(this.externalPath + "/_rels/.rels");
    relsDir.renameTo(renameDir);

return true;
}

private void copy(String outFileRelativePath){
    String files[] = null;
    try {
        files = this.mAssetManager.list(ASSETS_RELATIVE_PATH + outFileRelativePath);
    } catch (IOException e) {
        e.printStackTrace();
    }

String assetFilePath = null;
    for(String fileName : files){
        if(!fileName.contains(".")) {
            String outFile = outFileRelativePath + java.io.File.separator + fileName;
            copy(outFile);
        } else {
            File createFile = new File(this.externalPath + java.io.File.separator + outFileRelativePath);
            createFile.mkdir();
            File file = new File(createFile, fileName);

assetFilePath = 
                ASSETS_RELATIVE_PATH + outFileRelativePath + java.io.File.separator + fileName;

InputStream in = null;
            OutputStream out = null;
            try {
                in = this.mAssetManager.open(assetFilePath);
                out = new FileOutputStream(file);
                copyFile(in, out);
                in.close();
                out.flush();
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

private void copyFile(InputStream in, OutputStream out) throws IOException {
    byte[] buffer = new byte[1024];
    int read;
    while((read = in.read(buffer)) != -1){
        out.write(buffer, 0, read);
    }
}

private void zipFolder(String srcFolder, String destZipFile) throws Exception{
    FileOutputStream fileWriter = new FileOutputStream(destZipFile);
    ZipOutputStream zip = new ZipOutputStream(fileWriter);
    zip.setMethod(Deflater.DEFLATED);
    zip.setLevel(ZipOutputStream.STORED);

addFolderToZip(this.externalPath, "", zip);

zip.finish();
    zip.close();
}

private void addFolderToZip(String externalPath, String folder, ZipOutputStream zip){
    File file = new File(externalPath);
    String files[] = file.list();

for(String fileName : files){
        try {
            File currentFile = new File(externalPath, fileName);
            if(currentFile.isDirectory()){
                String outFile = externalPath + java.io.File.separator + fileName;          
                addFolderToZip(outFile, folder + java.io.File.separator + fileName, zip);
            } else {
                byte[] buffer = new byte[8000];
                int len;
                FileInputStream in = new FileInputStream(currentFile);
                zip.putNextEntry(new ZipEntry(folder + java.io.File.separator + fileName));
                while((len = in.read(buffer)) > 0){
                    zip.write(buffer, 0, len);
                }
                zip.closeEntry();
                in.close();
            }
        } catch (IOException e) {
                e.printStackTrace();
        }
    }
}

Edit

Here’s the code I wrote based on what @edi9999 says below in order to make it work. I’ve created a separate class that I’ll extend and add to and maybe do some cleanup, but this is valid code. It adds all files in the directory to the zip file and recursively calls itself to add all child files and folders.

private class Zip {
    private ZipOutputStream mZipOutputStream;
    private String pathToZipDestination;
    private String pathToFilesToZip;

public Zip(String pathToZipDestination, String pathToFilesToZip) {
        this.pathToZipDestination = pathToZipDestination;
        this.pathToFilesToZip = pathToFilesToZip;
    }

public void zipFiles() throws Exception{
        FileOutputStream fileWriter = new FileOutputStream(pathToZipDestination);
        this.mZipOutputStream = new ZipOutputStream(fileWriter);
        this.mZipOutputStream.setMethod(Deflater.DEFLATED);
        this.mZipOutputStream.setLevel(8);

AddFilesToZip("");

this.mZipOutputStream.finish();
        this.mZipOutputStream.close();
    }

private void AddFilesToZip(String folder){
        File mFile = new File(pathToFilesToZip + java.io.File.separator + folder);
        String mFiles[] = mFile.list();

for(String fileName : mFiles){
            File currentFile;
            if(folder != "")
                currentFile = new File(pathToFilesToZip, folder + java.io.File.separator + fileName);
            else
                currentFile = new File(pathToFilesToZip, fileName);
            if(currentFile.isDirectory()){
                if(folder != "")
                    AddFilesToZip(folder + java.io.File.separator + currentFile.getName());
                else
                    AddFilesToZip(currentFile.getName());
            } else {
                try{
                    byte[] buffer = new byte[8000];
                    int len;
                    FileInputStream in = new FileInputStream(currentFile);
                    if(folder != ""){
                        mZipOutputStream.putNextEntry(new ZipEntry(folder + java.io.File.separator + fileName));
                    } else {
                        mZipOutputStream.putNextEntry(new ZipEntry(fileName));
                    }
                    while((len = in.read(buffer)) > 0){
                        mZipOutputStream.write(buffer, 0, len);
                    }
                    mZipOutputStream.closeEntry();
                    in.close();
                } catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }
}

Solution

I

guess I have some problem.

When I open your corrupted File , and then open it on winrar, I see a backslash at the beginning of the folder, This is unusual:

Content of the corrupted Zip

When I recompress the file after unzipping it, the backslash is no longer there and the file opens in Word, so I think this should be the problem.

Content of the corrected Zip

I think the code here is wrong :

String outFile = externalPath + java.io.File.separator + fileName;  

It should be

if (externalPath=="")
    String outFile = externalPath + fileName;  
else 
    String outFile = externalPath + java.io.File.separator + fileName;  

Related Problems and Solutions