使用压缩生成的损坏的docx

时间:2013-06-08 02:22:18

标签: java android zip docx

首先我要说的是我在这里创建了一个帐户,因为我一直在靠墙打我的头以试图弄清楚这一点,所以就这样了。

此外,我已经看到了这个问题here.这些答案中的任何一个都没有帮助,我已经尝试了这两个问题。

我需要创建一个包含简单表格和数据的word文档。我决定创建一个示例文档,在其中获取创建文档所需的xml。我将所有文件夹从解压缩的docx文件移动到我的资源文件夹中。一旦我意识到我无法写入assets文件夹,我写了一个方法将所有文件和文件夹复制到设备的外部存储位置,然后将我创建的文档写入同一位置。从那里我试图将文件压缩回一个.docx文件。这是事情不起作用的地方。

创建了实际的docx文件,我可以通过DDMS将其移动到我的计算机,但是当我去查看它时,Word说它已损坏。虽然有些奇怪,如果我解压缩然后在我的计算机上重新压缩它而不做任何改变它是如何工作完美的。我使用了一个名为DiffMerge的程序(用于mac)将示例解压缩的docx文件与我创建的解压缩的docx进行比较,它说它们完全相同。所以,我认为这与Android中的压缩过程有关。

我还尝试在我的计算机上解压缩示例docx文件,将所有文件和文件夹移动到我的assets文件夹,包括document.xml文件,然后尝试将其压缩,而不添加我自己的document.xml文件并使用样本一,也不起作用。我尝试的另一件事是将实际的docx文件放在我的资源文件夹中,将其解压缩到我的外部存储器上,然后重新压缩它而不做任何事情。这也失败了。

我基本上不知所措。请有人帮我解决这个问题。

以下是我的一些代码:

    首先调用
  1. moveDocxFoldersFromAssetsToExternalStorage()。
  2. 在调用之后,所有文件都被移过。
  3. 然后,我创建document.xml文件并将其放在它所属的word目录中
  4. 一切都应该是,我现在尝试创建zip文件。
  5. 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();
            }
        }
    }
    

    修改

    这是我编写的代码,以便根据@ edi9999在下面说的内容使其正常工作。我创建了一个单独的类,我将扩展并添加,并可能清理一点,但这是工作代码。它将目录中的所有文件添加到zip文件中,并递归调用自身以添加所有子文件和文件夹。

    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();
                    }
                }
            }
        }
    }
    

1 个答案:

答案 0 :(得分:4)

我想我有什么不对。

当我打开你的corrupted File并在winrar上打开它时,我在文件夹的开头看到了反义词,这很不寻常:

Content of the corrupted Zip

当我解压缩文件后重新压缩文件时,反斜杠不再存在,文件在Word中打开,所以我认为这应该是问题。

Content of the corrected Zip

我觉得这里的代码错了:

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

应该是

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