[英]Java: Add files to zip-file recursively but without full path
I am trying to put files from a folder inside a zip file in the following structure: 我试图将文件从zip文件中的文件夹中放入以下结构:
Folder structure:
myFolder
|-file1.txt
|-file2.txt
|-folder172
|-file817.txt
|-file818.txt
...
Supposed structure inside ZipFile:
file1.txt
file2.txt
folder172
|-file817.txt
|-file818.txt
This is my code: 这是我的代码:
public static void writeZip(String path) throws IOException{
FileOutputStream fos = new FileOutputStream(path+File.separator+"atest.zip");
ZipOutputStream zos = new ZipOutputStream(fos);
try {
Files.walk(Paths.get(path)).filter(Files::isRegularFile).forEach((string) -> addToZipFile(string.toString(),zos));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
zos.close();
fos.close();
}
public static void addToZipFile(String fileName, ZipOutputStream zos) throws IOException {
System.out.println("Writing '" + fileName + "' to zip file");
File file = new File(fileName);
FileInputStream fis = null;
fis = new FileInputStream(file);
ZipEntry zipEntry = new ZipEntry(fileName);
zos.putNextEntry(zipEntry);
byte[] bytes = new byte[1024];
int length;
while ((length = fis.read(bytes)) >= 0) {
zos.write(bytes, 0, length);
}
zos.closeEntry();
fis.close();
}
The problem is now, when i call writeZip("/home/arthur/.grutil/");
问题是,当我调用
writeZip("/home/arthur/.grutil/");
, i get the following structure in the zip-file: ,我在zip文件中得到以下结构:
home
|-arthur
|-.grutil
|-file1.txt
|-file2.txt
|-folder172
|-file817.txt
|-file818.txt
...
How do i need to change my code to get the supposed structure (as described above) and not the structure with the full path '/home/arthur/.grutil/ ...'? 我如何更改我的代码以获得所谓的结构(如上所述)而不是具有完整路径'/home/arthur/.grutil/ ...'的结构?
Whilst this can be done with the ancient ZipOutputStream
I would recommend against it. 虽然这可以用古老的
ZipOutputStream
来完成,但我建议不ZipOutputStream
。
It is much more intuitive to think about a Zip archive as a compressed filesystem inside a file, than a stream of bytes. 将Zip存档视为文件中的压缩文件系统比将字节流更直观。 For this reason, Java provides the
ZipFileSystem
. 出于这个原因,Java提供了
ZipFileSystem
。
So all you need to do is open the Zip as a FileSystem
and then manually copy files across. 因此,所有你需要做的就是打开拉链作为一个
FileSystem
,然后跨过手动复制文件。
There are a couple of gotchas: 有几个陷阱:
relativize
across different filesystems (reasons should be obvious) so this you need to do yourself. relativize
操作(原因应该是显而易见的)所以你需要自己做。 Here are a couple of simple methods that will do exactly that: 这里有几个简单的方法可以做到这一点:
/**
* This creates a Zip file at the location specified by zip
* containing the full directory tree rooted at contents
*
* @param zip the zip file, this must not exist
* @param contents the root of the directory tree to copy
* @throws IOException, specific exceptions thrown for specific errors
*/
public static void createZip(final Path zip, final Path contents) throws IOException {
if (Files.exists(zip)) {
throw new FileAlreadyExistsException(zip.toString());
}
if (!Files.exists(contents)) {
throw new FileNotFoundException("The location to zip must exist");
}
final Map<String, String> env = new HashMap<>();
//creates a new Zip file rather than attempting to read an existing one
env.put("create", "true");
// locate file system by using the syntax
// defined in java.net.JarURLConnection
final URI uri = URI.create("jar:file:/" + zip.toString().replace("\\", "/"));
try (final FileSystem zipFileSystem = FileSystems.newFileSystem(uri, env);
final Stream<Path> files = Files.walk(contents)) {
final Path root = zipFileSystem.getPath("/");
files.forEach(file -> {
try {
copyToZip(root, contents, file);
} catch (IOException e) {
throw new RuntimeException(e);
}
});
}
}
/**
* Copy a specific file/folder to the zip archive
* If the file is a folder, create the folder. Otherwise copy the file
*
* @param root the root of the zip archive
* @param contents the root of the directory tree being copied, for relativization
* @param file the specific file/folder to copy
*/
private static void copyToZip(final Path root, final Path contents, final Path file) throws IOException {
final Path to = root.resolve(contents.relativize(file).toString());
if (Files.isDirectory(file)) {
Files.createDirectories(to);
} else {
Files.copy(file, to);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.