代码之家  ›  专栏  ›  技术社区  ›  Guillaume

Java:如何获得压缩字节数组的字符串表示形式?

  •  1
  • Guillaume  · 技术社区  · 14 年前

    我想将一些压缩数据放入远程存储库。
    要将数据放在此存储库中,我只能使用将资源及其内容的名称作为字符串的方法。(就像data.txt+“Hello World”)。
    存储库正在消耗文件系统,但不是,所以我不能直接使用文件。

    我希望能够执行以下操作:

    1. 客户端向服务器发送“data.txt”文件
    2. 服务器将“data.txt”压缩为压缩文件“data.zip”
    3. 服务器将data.zip的字符串表示形式发送到存储库
    4. 存储库存储数据.zip
    5. 客户机从repository data.zip下载,他可以用自己最喜欢的zip工具打开它。

    问题出现在步骤3 当我试图获得压缩文件的字符串表示形式时。

    这里是一个示例类,使用zip*流,并模拟展示我的问题的存储库。
    创建的zip文件正在工作,但在其“序列化”之后,它会损坏。
    (示例类使用jakarta commons.io)

    非常感谢你的帮助。

    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
    
        }
    
    }
    
    2 回复  |  直到 14 年前
        1
  •  1
  •   leonbloy    14 年前

    服务器发送的字符串表示形式 data.zip到存储库

    因此,您希望获得一个zip(即二进制)流的字符串(即文本)表示。

    Base64 这是最流行的方法。

    一个流行的Java实现来自 Apache commons ( codec 组件)

        2
  •  2
  •   crazyscot    14 年前

    zip文件是二进制的。Java中的字符串处理是文本的,可能会把它看作CRLFs、零字节和EOF标记。当涉及到读取和重写zipfile时,我建议您尝试 readFileToByteArray writeByteArrayToFile 作为一个实验。如果这行得通的话,我会怀疑是字符串处理造成的。