Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何以最小的工作空间压缩此文件夹,以便用Java解压_Java_Compression_Gzip_Tar - Fatal编程技术网

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

如何以最小的工作空间压缩此文件夹,以便用Java解压,java,compression,gzip,tar,Java,Compression,Gzip,Tar,我有一个文件夹,其中包含在linux上创建的文件,我目前使用gzip(即tar.gz)对这些文件进行tar和压缩 然后在稍后的阶段,该文件被复制到另一台linux机器上的一个文件系统中,并使用Java提取到另一个文件系统中 我的问题是存档是3GB压缩,5GB未压缩。这两个文件系统分别是4GB和6GB。我将压缩的归档文件复制到4GB fs,但当我尝试将其解压缩到6GB时,它会在解压缩时复制到6GB fs,因此6GB需要足够的空间来容纳压缩和未压缩的格式 我不清楚为什么要创建这个临时文件,如果我这么

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

然后在稍后的阶段,该文件被复制到另一台linux机器上的一个文件系统中,并使用Java提取到另一个文件系统中

我的问题是存档是3GB压缩,5GB未压缩。这两个文件系统分别是4GB和6GB。我将压缩的归档文件复制到4GB fs,但当我尝试将其解压缩到6GB时,它会在解压缩时复制到6GB fs,因此6GB需要足够的空间来容纳压缩和未压缩的格式

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

cd destination folder
tar -zxvf source file
它可以在不耗尽空间的情况下工作,但我需要使用纯Java而不是命令行来解压缩它


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

你让我对这一个感到好奇,是的,这并不难。我使用TCP服务器和客户机只是为了完全分离输入/输出流,以确保没有欺诈行为

实际上,在服务器上读取原始ZIP数据并将其发送到客户端。然后,客户端将该数据解释为
ZipInputStream
,并将所有条目写入输出文件夹。事实证明,您甚至不需要发送大块数据,只需要真正分配缓冲区。我分析了它发送超过200mb的zip文件时的内存消耗情况

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

我为ZIP文件编写了这段代码,因为我没有注意到,但我想我会在anway上发布。您可以在线使用一些库对其进行调整,以使用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();
    }
}

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

cd foldertozip
gzip *
cd ..
tar -cvf foldertozip.tar folderzip
tar的大小与原始的foldertozip.tar.gz完全相同,但不需要临时步骤

然后我可以:

  • 将foldertozip.tar复制到4GB fs
  • 将foldertozip.tar解压缩到6GB fs
  • 对于foldertozip中的每个文件 解压缩每个.gz
因此,我们在6GB fs上使用的唯一额外临时空间是解压缩每个gz文件所需的空间


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

在传输数据时开始解压缩它?我说发送300mb的压缩数据块,然后一次解压缩一个,在这两种情况下,您都可以保持在1gb的利润范围内side@ug_请提供更多详细信息,我如何将文件分割成可以独立解压缩的块?感谢您的努力,但不幸的是,您的回答没有抓住关键点,即文件被涂上焦油,然后被gzip压缩,因此必须先被gzip压缩成普通焦油,然后才能恢复。我现在有一个解决方案,我将在一分钟后发布