我想从7-zip字节流中提取一些文件,它不能存储在硬盘上,所以我不能使用RandomAccessFile类,我已阅读 sevenzipjbinding 源代码,它还使用其他语言写的 lib7-Zip-JBinding.so 等封闭源代码来解压缩文件。官方软件包的方法 SevenZip
SevenZip.Compression.LZMA.Decoder.Code(java.io.InputStream inStream,java.io.OutputStream outStream,long outSize,ICompressProgressInfo progress)
只能解压缩单个文件。
那么如何用纯Java解压缩7-zip字节流?
任何人都有解决方案吗?
抱歉我的英语不好,我在网上等你的回答。
答案 0 :(得分:11)
Commons compress 1.6及以上版本支持操作7z格式。试试吧。
参考:
http://commons.apache.org/proper/commons-compress/index.html
示例:
SevenZFile sevenZFile = new SevenZFile(new File("test-documents.7z"));
SevenZArchiveEntry entry = sevenZFile.getNextEntry();
while(entry!=null){
System.out.println(entry.getName());
FileOutputStream out = new FileOutputStream(entry.getName());
byte[] content = new byte[(int) entry.getSize()];
sevenZFile.read(content, 0, content.length);
out.write(content);
out.close();
entry = sevenZFile.getNextEntry();
}
sevenZFile.close();
答案 1 :(得分:1)
由于7z解压缩需要随机访问,因此您必须将整个流读入byte[]
并使用new SevenZFile(new SeekableInMemoryByteChannel(bytes))
。 (如果它长于Integer.MAX_VALUE
个字节,则必须创建一个自定义SeekableByteChannel
实现。)一旦实例被构造,其过程与SANN3的答案相同。
如果它不适合存储在 中,并且您不能将其写入临时文件,那么7zip由于需要随机访问,因此不是合适的压缩算法。
答案 2 :(得分:0)
代码对我有用:
pom.xml添加:
<!-- Unzip 7z -->
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-compress -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.20</version>
</dependency>
<!-- Unzip 7z dependancy with commons-compress for 7z-->
<!-- https://mvnrepository.com/artifact/org.tukaani/xz -->
<dependency>
<groupId>org.tukaani</groupId>
<artifactId>xz</artifactId>
<version>1.8</version>
</dependency>
添加到课程
public static String unzip(final String directory, final String fileName) {
final StringBuilder sb = new StringBuilder();
final File fDirectory = new File(directory);
final File input7z = new File(fDirectory, fileName);
try (final SevenZFile sevenZFile = new SevenZFile(input7z)) {
SevenZArchiveEntry entry = sevenZFile.getNextEntry();
while (entry != null) {
LOGGER.info("Treatment of entry : {}", entry.getName());
try (final FileOutputStream out = new FileOutputStream(new File(fDirectory, entry.getName()))) {
byte[] content = new byte[(int) entry.getSize()];
sevenZFile.read(content, 0, content.length);
out.write(content);
} catch (final IOException ioe) {
final String error = "Error when writing entry " + entry.getName();
LOGGER.error(error);
sb.append(error).append("\n");
}
entry = sevenZFile.getNextEntry();
}
} catch (final IOException ioe) {
final String error = "Error when reading entry " + fileName;
LOGGER.error(error);
sb.append(error).append("\n");
}
return sb.length() == 0 ? null : sb.toString();
}
更新:
无商店:
public static String getContentOneFile(final String directory, final String fileName) throws IOException {
final List<String> subFilenames = ls(directory, fileName);
if (subFilenames.size() == 1) {
return getContent(directory, fileName, subFilenames.get(0));
} else if (subFilenames.size() == 0) {
throw new IOException("No file found in 7zip : " + directory + ":" + fileName);
} else {
throw new IOException("Can not extract data from many document. Please specify subFilename in " + subFilenames);
}
}
使用ls方法:
public static List<String> ls(final String directory, final String fileName) throws IOException {
final List<String> out = new ArrayList<>();
final File fDirectory = new File(directory);
final File input7z = new File(fDirectory, fileName);
try (final SevenZFile sevenZFile = new SevenZFile(input7z)) {
SevenZArchiveEntry entry = sevenZFile.getNextEntry();
while (entry != null) {
out.add(entry.getName());
entry = sevenZFile.getNextEntry();
}
} catch (final IOException ioe) {
final String error = "Error when reading entry " + fileName;
LOGGER.error(error);
throw ioe;
}
return out;
}
并使用getContent方法:
public static String getContent(final String directory, final String fileName, final String subFileName) throws IOException {
String out = null;
final File fDirectory = new File(directory);
final File input7z = new File(fDirectory, fileName);
try (final SevenZFile sevenZFile = new SevenZFile(input7z)) {
SevenZArchiveEntry entry = sevenZFile.getNextEntry();
while (entry != null) {
LOGGER.info("Treatment of entry : {}", entry.getName());
if (subFileName.equals(entry.getName())) {
byte[] content = new byte[(int) entry.getSize()];
sevenZFile.read(content, 0, content.length);
out = new String(content);
}
entry = sevenZFile.getNextEntry();
}
} catch (final IOException ioe) {
final String error = "Error when reading entry " + fileName;
LOGGER.error(error);
throw ioe;
}
return out;
}