如何从URL直接提取tar文件?Java实现方案咨询
直接从URL提取tar.xz文件的问题及解决方案
问题描述
需要直接从远程URL流式提取tar文件,目标示例文件为freedict-deu-eng-1.9-fd1.dictd.tar.xz。尝试用JDK自带的GZIPInputStream结合URLConnection实现,代码如下:
URL url = new URL(zipFileUrl); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); InputStream inputStream = connection.getInputStream(); GZIPInputStream gzipInputStream = new GZIPInputStream(inputStream);
运行后触发错误:java.util.zip.ZipException: Not in GZIP format。
目前可以通过先下载文件到本地、提取后删除的方式解决,但这种方案用户体验差,希望找到类似ZipInputStream遍历ZipEntry的流式处理方案。
解决方案
JDK自带的GZIPInputStream仅支持gzip压缩格式,而目标文件采用的是xz压缩算法,需要借助第三方库实现流式解压:
方案1:使用Apache Commons Compress(推荐)
这是Java生态中处理压缩归档的常用库,支持多种格式,API稳定且公开。
- 引入Maven依赖:
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-compress</artifactId> <version>1.24.0</version> </dependency>
- 流式解压并处理tar条目:
import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; import org.apache.commons.compress.compressors.xz.XZCompressorInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; public class TarXzStreamHandler { public static void main(String[] args) throws IOException { String targetUrl = "https://download.freedict.org/dictionaries/deu-eng/1.9-fd1/freedict-deu-eng-1.9-fd1.dictd.tar.xz"; URL url = new URL(targetUrl); URLConnection connection = url.openConnection(); try (InputStream rawStream = connection.getInputStream(); XZCompressorInputStream xzStream = new XZCompressorInputStream(rawStream); TarArchiveInputStream tarStream = new TarArchiveInputStream(xzStream)) { TarArchiveEntry entry; while ((entry = tarStream.getNextTarEntry()) != null) { if (!entry.isDirectory()) { System.out.println("处理文件:" + entry.getName()); // 读取文件内容并处理,示例:写入本地或内存处理 byte[] buffer = new byte[1024]; int readBytes; while ((readBytes = tarStream.read(buffer)) != -1) { // 这里添加自定义处理逻辑,比如写入输出流 } } } } } }
方案2:使用单独的XZ压缩库
如果不想引入完整的Commons Compress,可以使用专门的XZ Java库:
- 引入Maven依赖:
<dependency> <groupId>org.tukaani</groupId> <artifactId>xz</artifactId> <version>1.9</version> </dependency>
- 结合JDK非公开API的
TarInputStream(注意:该API属于Sun/Oracle私有实现,可能在不同JDK版本中存在兼容性问题):
import org.tukaani.xz.XZInputStream; import com.sun.tools.tar.TarInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; public class XzTarStreamHandler { public static void main(String[] args) throws IOException { String targetUrl = "https://download.freedict.org/dictionaries/deu-eng/1.9-fd1/freedict-deu-eng-1.9-fd1.dictd.tar.xz"; URL url = new URL(targetUrl); URLConnection connection = url.openConnection(); try (InputStream rawStream = connection.getInputStream(); XZInputStream xzStream = new XZInputStream(rawStream); TarInputStream tarStream = new TarInputStream(xzStream)) { com.sun.tools.tar.TarEntry entry; while ((entry = tarStream.getNextEntry()) != null) { if (!entry.isDirectory()) { System.out.println("处理文件:" + entry.getName()); byte[] buffer = new byte[1024]; int readBytes; while ((readBytes = tarStream.read(buffer)) != -1) { // 自定义处理逻辑 } } } } } }
关键说明
- 报错根源:
GZIPInputStream仅能解析gzip格式(.gz),而目标文件是xz压缩格式(.xz),两种压缩算法不兼容,因此抛出格式错误。 - 流式处理优势:无需下载完整文件到本地,边下载边解压处理,节省磁盘空间同时提升响应效率。
内容的提问来源于stack exchange,提问作者Lasnik
相关产品推荐
相关产品推荐

