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

发布于 2024-09-02 03:42:50 字数 4120 浏览 5 评论 0原文

我想将一些压缩数据放入远程存储库。
为了将数据放入此存储库,我只能使用一种将资源名称及其内容作为字符串的方法。 (如 data.txt + “hello world”)。
存储库正在模拟文件系统,但事实并非如此,因此我无法直接使用文件。

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

  1. 客户端向服务器发送文件“data.txt”
  2. 服务器将“data.txt”压缩为压缩文件“data.zip”
  3. 服务器将 data.zip 的字符串表示形式发送到存储库
  4. 存储库存储 data.zip
  5. 客户端从存储库 data.zip 下载,并且他能够使用其最喜欢的 zip 工具打开它

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

这是一个示例类,使用 zip*stream 并模拟展示我的问题的存储库。
创建的 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

    }

}

I want to put some compressed data into a remote repository.
To put data on this repository I can only use a method that take the name of the resource and its content as a String. (like data.txt + "hello world").
The repository is moking a filesystem but is not, so I can not use File directly.

I want to be able to do the following:

  1. client send to server a file 'data.txt'
  2. server compress 'data.txt' into a compressed file 'data.zip'
  3. server send a string representation of data.zip to the repository
  4. repository store data.zip
  5. client download from repository data.zip and his able to open it with its favorite zip tool

The problem arise at step 3 when I try to get a string representation of my compressed file.

Here is a sample class, using the zip*stream and that emulate the repository showcasing my problem.
The created zip file is working, but after its 'serialization' it's get corrupted.
(the sample class use jakarta commons.io )

Many thanks for your help.

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

    }

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

怂人 2024-09-09 03:42:50

Zip 文件是二进制的。 Java 中的字符串处理是文本性的,可能会破坏 CRLF、零字节和 EOF 标记等内容。当涉及到读取和重写 zip 文件时,我建议您尝试使用 readFileToByteArraywriteByteArrayToFile 作为实验。如果这有效,那么我怀疑字符串处理是罪魁祸首。

Zip files are binary. String handling in Java is textual and might be mangling what it sees as CRLFs, zero bytes and EOF markers. When it comes to reading and rewriting the zipfile, I suggest you try with readFileToByteArray and writeByteArrayToFile as an experiment. If that works then I'd suspect the String handling is to blame.

意中人 2024-09-09 03:42:50

服务器发送一个字符串表示
data.zip 到存储库

因此您想要获取 zip(即二进制)流的字符串(即文本)表示形式。

Base64 是最流行的方法。

一种流行的 Java 实现来自 Apache commons编解码器组件)

server send a string representation of
data.zip to the repository

So you want to get a string (i.e. textual) representation of a zip (i.e. binary) stream.

Base64 is the most popular way to do this.

One popular Java implementation is from Apache commons (codec component)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文