如何最好地压缩此文件夹,以便用最少的工作空间解压缩Java

时间:2014-06-30 21:27:48

标签: java compression gzip tar

我有一个文件夹,其中包含在linux上创建的文件,我目前使用gzip进行tar压缩(即tar.gz)

然后在稍后阶段将文件复制到另一台Linux机器到一个文件系统,然后使用Java将其解压缩到另一个文件系统。

我的问题是存档是3GB压缩,5GB未压缩。两个文件系统是4GB和6GB我将压缩存档复制到4GB fs但是当我尝试将其解压缩到6GB时,它被复制到6GB fs,因为它是未压缩的,因此6GB需要足够的空间用于压缩和未压缩的格式,但它没有。

我不清楚为什么要创建这个临时文件,如果我这样做

cd destination folder
tar -zxvf source file

它可以在没有空间不足的情况下工作,但我需要使用纯Java而不是命令行解压缩它

是否有更好的方法来压缩文件夹,因为我不受任何特定格式的限制,只要它可以用Java代码解压缩即可。我无法修改/重新配置两个文件系统的大小 - 它需要在这些边界内工作。

2 个答案:

答案 0 :(得分:1)

仅供参考:刚刚意识到在tar.gz文件中文件被涂焦,然后tar文件被gzip压缩,因此当解压缩到tar的临时步骤时很难避免。但是,如果我手动gzip每个文件然后tar ,如下所示:

cd foldertozip
gzip *
cd ..
tar -cvf foldertozip.tar folderzip

foldertozip.tar的大小与原始的foldertozip.tar.gz完全相同,但不需要临时步骤。

然后我可以:

  • 将foldertozip.tar复制到4GB fs
  • Untar foldertozip.tar至6GB fs
  • 对于foldertozip中的每个文件   解压每个.gz

因此我们在6GB fs上使用的唯一额外临时空间是解压缩每个gz文件所需的空间。

我已经对此进行了测试,它对我有用。

答案 1 :(得分:0)

你让我对这个感到好奇,而且这并不困难。我使用TCP服务器和客户端只是为了完全分离输入/输出流,以确保没有恶作剧。

基本上读取服务器上的原始ZIP数据并将其发送到客户端。然后,客户端将该数据解释为ZipInputStream,并将所有条目写入输出文件夹。事实证明,你甚至不需要发送大块数据,只有缓冲区才真正分配。我发现它发送了一个200mb的zip文件,内存消耗几乎没有开始。

你最后得到了一个不错的SocketException,但这是预期的,因为我几乎没有添加任何错误处理而不是必需的。客户端关闭连接,服务器不喜欢这样,所以它会抛出一个错误,但所有数据都已完成,所以谁在乎呢!

我为ZIP文件编写了这段代码,因为我没有注意,但我想我会先发帖子。您可以使用某些库在线调整它以使用TAR输入流但代码应该给出一般的Jist。

/**
 * @param args
 * @throws Exception
 */
public static void main(String[] args) throws Exception {
    Object serverWait = new Object();
    startServer(serverWait);
    synchronized (serverWait) {
        // make sure our server is started and accepting clients, otherwise we run the risk of starting the client before the server is started
        serverWait.wait(2000);
    }
    startClient();
}

private static void startServer(final Object serverWait) {
    new Thread(new Runnable() {
        @Override
        public void run() {

            ServerSocket serverSocket = null;
            Socket socket = null;
            InputStream is = null;
            try {
                serverSocket = new ServerSocket(5555);
                synchronized (serverWait) {
                    serverWait.notify();
                }
                socket = serverSocket.accept();
                System.out.println("Client accepted, sending data");
                // just send over the raw zip file and let the client sort through how to parse it
                is = new FileInputStream("f:\\so\\zip_transfer\\ZipFile.zip");

                int numRead = 0;
                byte [] buffer = new byte[2048];
                while((numRead = is.read(buffer)) != -1) {
                    socket.getOutputStream().write(buffer, 0, numRead);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                safeClose(socket);
                safeClose(serverSocket);
                safeClose(is);
            }
        }
    }).start();
}


private static void startClient() {
    new Thread(new Runnable() {
        @Override
        public void run() {

            Socket socket = null;
            ZipInputStream is = null;
            try {
                socket = new Socket("127.0.0.1", 5555);
                System.out.println("Client connected, retrieving data");

                // the data we are receiving is in zip format
                is = new ZipInputStream(socket.getInputStream());
                extactZipInputStream(is, new File("f:\\so\\zip_transfer\\OutputDirectory"));

            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                safeClose(socket);
                safeClose(is);
            }
        }
    }).start();
}

public static void extactZipInputStream(ZipInputStream is, File outputFolder) throws ZipException, IOException  {

    ZipEntry entry = null;
    // Just keep going until we dont have any entries left.
    while((entry = is.getNextEntry()) != null) {
        System.out.println("Entry: " + entry.getName());
        File file = new File(outputFolder, entry.getName());
        if(entry.isDirectory()) {
            // make all the path a direcotyr
            file.mkdirs();
        } else {
            // last one isnt a directory its our file, only make our parents
            file.getParentFile().mkdirs();

            // write the file to the system
            FileOutputStream fos = new FileOutputStream(file);
            int numRead = 0;
            byte [] buffer = new byte[2048];
            while((numRead = is.read(buffer)) != -1) {
                fos.write(buffer, 0, numRead);
            }
            fos.close();
        }

        is.closeEntry();
    }
}

private static void safeClose(Closeable closable) {
    try {
        if(closable != null) {
            closable.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}