如何最好地压缩此文件夹,以便可以使用 Java 以最小的工作空间解压缩
Posted
技术标签:
【中文标题】如何最好地压缩此文件夹,以便可以使用 Java 以最小的工作空间解压缩【英文标题】:How best to compress this folder so can be uncompressed withi Java with minimum working space 【发布时间】:2014-06-30 21:27:48 【问题描述】:我有一个文件夹,其中包含在 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 代码解压缩。我无法修改/重新配置两个文件系统的大小 - 它需要在这些边界内工作。
【问题讨论】:
在传输数据时开始解压缩?我说以 300mb 的压缩数据块发送它并一次解压缩一个,你会很好地保持在两边的 1gb 余量内 @ug_ 更多细节请我如何分解成可以独立解压缩的块? 【参考方案1】:仅供参考:刚刚意识到在 tar.gz 文件中,文件被 tar 压缩,然后 tar 文件被 gzip 压缩,因此在解压缩时很难避免解压缩到 tar 的中间步骤。但是,如果我手动 gzip 每个文件,然后 tar 如下:
cd foldertozip
gzip *
cd ..
tar -cvf foldertozip.tar folderzip
foldertozip.tar 的大小与原来的foldertozip.tar.gz 完全相同,但不需要中间步骤。
然后我可以:
将 foldertozip.tar 复制到 4GB fs 将 foldertozip.tar 解压到 6GB fs 对于 foldertozip 中的每个文件 解压每个.gz所以我们在 6GB fs 上使用的唯一额外临时空间是解压缩每个 gz 文件所需的空间。
我已经对此进行了测试,它对我有用。
【讨论】:
【参考方案2】:你让我对这个很好奇,是的,这并不难。我使用 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();
【讨论】:
感谢您的努力,但不幸的是,您的回答错过了文件被 tar 化然后 gzip 压缩的关键点,因此必须在解压缩之前将其 gzip 压缩成普通的 tar。我现在有一个解决方案,我会在一分钟内发布以上是关于如何最好地压缩此文件夹,以便可以使用 Java 以最小的工作空间解压缩的主要内容,如果未能解决你的问题,请参考以下文章
Java实现打包压缩文件或文件夹生成zip以实现多文件批量下载