我有一个简单的文件系统复制例程,它会在基于ZIP的文件系统中遇到麻烦。我的代码相对通用,因为它没有专门引用ZIP类,即。它使用FileSystem
,Files.walkFileTree()
和Files.copy()
。
大多数情况下,我的代码按预期工作,即。将ZIP文件安全地复制(解压缩)到目标目录中。当其中一个ZIP条目名称中包含异常字符时,它会中断。我没有异常的精确定义,但它似乎是带有重音的字符,例如。 é
。
这是我的代码的重要部分。 copyFileSystem()
遍历通过文件系统,并使用FileCopyVisitor
逐个复制每个文件。 (我这样做,所以我可以报告整个副本的进度 - 这个代码没有显示。)
public static boolean copyFileSystem(File src, File dest)
{
boolean success = false;
try (FileSystem fs = FileSystems.newFileSystem(src.toPath(), null))
{
Path root = fs.getPath("/");
Files.walkFileTree(root, new FileCopyVisitor(dest));
success = true;
}
catch (IOException | RuntimeException e)
{
LOG.error("Error copying file system", e);
}
return success;
}
class FileCopyVisitor implements FileVisitor<Path>
{
public FileVisitResult visitFile(Path src, BasicFileAttributes attrs)
throws IOException
{
File dest = new File(destinationDirectory, src.toString()); // <<==== error is here
Files.copy(src, dest.toPath(), StandardCopyOption.REPLACE_EXISTING);
return FileVisitResult.CONTINUE;
}
}
问题是调用src.toString()
中的visitFile()
来查找要复制的文件的名称。如果FileSystem
为ZipFileSystem
,则src
为ZipPath
。当文件名包含重音时,对toString()
的调用失败,其中IllegalArgumentException
带有(令人沮丧的简短)消息MALFORMED[1]
。 (当Path
为File
时,src.toFile()
不支持使用src
代替ZipPath
。{/ p>
我试图通过完全避免调用toString()
来解决这个问题,因此:
Path dest = destinationDirectory.toPath().resolve(src);
然而,这会产生ProviderMismatchException
,大概是因为目标目录是Windows文件系统,而src
属于ZipFileSystem
。
我确实设法使用反射解决了这个问题。也就是说,如果src.toString()
引发异常,那么我会检查src
是否为ZipPath
,如果是,请使用反射来访问其隐藏的私有path
字段文件名。我想我们都同意这是一个坏事 TM 。
有没有人对更好的处理方法有什么建议?