Java Zip文件系统提供程序:远程驱动器[Windows]上的只读

Java Zip文件系统提供程序:远程驱动器[Windows]上的只读,java,filesystems,zip,java.nio.file,Java,Filesystems,Zip,Java.nio.file,我有一个问题:如果zip文件位于远程驱动器上(映射与否似乎无关),那么虚拟文件系统是只读的,尽管文件本身不是。我编写了一个简单的示例代码: public static void main(String[] args) throws IOException { File workingDir = new File(args[0]); File source = new File(workingDir, "in.zip"); File target = new File(wo

我有一个问题:如果zip文件位于远程驱动器上(映射与否似乎无关),那么虚拟文件系统是只读的,尽管文件本身不是。我编写了一个简单的示例代码:

public static void main(String[] args) throws IOException {
    File workingDir = new File(args[0]);
    File source = new File(workingDir, "in.zip");
    File target = new File(workingDir, "out.zip");
    Files.copy(source.toPath(), target.toPath(), StandardCopyOption.REPLACE_EXISTING);

    try (FileSystem zipfs = FileSystems.newFileSystem(target.toPath(), null)) {
        Path pathInZipfile = zipfs.getPath("test.xml");
        System.out.println("zipfile writable: " + target.canWrite());
        System.out.println("zipFS writable: " + !zipfs.isReadOnly());
        Files.delete(pathInZipfile);
        System.out.println("File successfully deleted");   
    } catch (IOException e) {
        e.printStackTrace();
    }
}
如果workingDir是本地目录,则一切正常。但是,如果它是(映射的)远程驱动器,我会得到:

zipfile writable: true
zipFS writable: false
Exception in thread "main" java.nio.file.ReadOnlyFileSystemException
    at com.sun.nio.zipfs.ZipFileSystem.checkWritable(ZipFileSystem.java:155)
    at com.sun.nio.zipfs.ZipFileSystem.deleteFile(ZipFileSystem.java:1335)
    at com.sun.nio.zipfs.ZipPath.delete(ZipPath.java:655)
    at com.sun.nio.zipfs.ZipFileSystemProvider.delete(ZipFileSystemProvider.java:206)
    at java.nio.file.Files.delete(Unknown Source)
    at zipfs.ZipFS.main(ZipFS.java:23)

我做错什么了吗?不可能吗?有解决方法吗?

尝试将
ZipFileSystem
中的私有字段
readOnly
设置为
false
,并进行反射。

尝试将
ZipFileSystem
中的私有字段
readOnly
设置为
false
并进行反射。

我遇到了同样的问题,然后查看了JDK代码

调查结果 在ZipFileSystem.java中,有三条相关的行:

zfpath.getFileSystem().provider().checkAccess(zfpath, AccessMode.READ);
if (!Files.isWritable(zfpath))
    this.readOnly = true;
zfPath是一个路径对象。Windows文件系统提供程序中的某些内容会阻止对zip存档路径的写入访问。似乎没有多少事情要做

变通办法 我使用的解决方法是:

  • 在临时文件夹中创建zip存档
  • 填充zip归档文件
  • 将临时文件复制到原始映射驱动器位置

  • 只要映射的驱动器在zip文件系统之外的上下文中是可写的,这个方法就可以工作。

    我遇到了同样的问题,我查看了JDK代码

    调查结果 在ZipFileSystem.java中,有三条相关的行:

    zfpath.getFileSystem().provider().checkAccess(zfpath, AccessMode.READ);
    if (!Files.isWritable(zfpath))
        this.readOnly = true;
    
    zfPath是一个路径对象。Windows文件系统提供程序中的某些内容会阻止对zip存档路径的写入访问。似乎没有多少事情要做

    变通办法 我使用的解决方法是:

  • 在临时文件夹中创建zip存档
  • 填充zip归档文件
  • 将临时文件复制到原始映射驱动器位置

  • 只要映射的驱动器在zip文件系统之外的上下文中是可写的,这种方法就可以工作。

    我们遇到了完全相同的问题,并且已经找到了某种野蛮的解决方案。
    FileSystems.newFileSystem(Path)
    接受
    Path
    接口,因此可以通过包装真实的
    Path
    实例来满足它

    以下是实现必需的
    FileSystemProvider.checkAccess()的解决方案

    private静态文件系统createZip(路径zipPath)
    抛出异常
    {
    var fileSystem=zipPath.getFileSystem();
    var provider=fileSystem.provider();
    返回FileSystems.newFileSystem(
    新路径()
    {
    专用路径(路径路径)
    {
    返回this==path?zipPath:path;
    }
    @凌驾
    公共文件系统getFileSystem()
    {
    返回新文件系统()
    {
    公共集supportedFileAttributeViews()
    {
    返回fileSystem.supportedFileAttributeViews();
    }
    @凌驾
    公共文件系统提供程序()
    {
    返回新的FileSystemProvider()
    {
    @凌驾
    公共空集合属性(
    路径路径,
    字符串属性,
    对象值,
    链接选项…选项)
    抛出IOException
    {
    setAttribute(路径、属性、值、选项);
    }
    @凌驾
    公共地图属性(
    路径路径,
    字符串属性,
    链接选项…选项)
    抛出IOException
    {
    返回提供者。
    读取属性(路径、属性、选项);
    }
    @凌驾
    公共A readAttributes(
    路径路径,
    类类型,
    链接选项…选项)
    抛出IOException
    {
    返回provider.readAttributes(路径、类型、选项);
    }
    @凌驾
    公共文件系统newFileSystem(URI、映射环境)
    抛出IOException
    {
    返回provider.newFileSystem(uri,env);
    }
    @凌驾
    公共目录流newDirectoryStream(
    路径目录,
    过滤器…属性)
    抛出IOException
    {
    返回provider.newByteChannel(路径、选项、属性);
    }
    @凌驾
    公开无效动议(
    路径源,
    路径目标,
    CopyOption…选项)
    抛出IOException
    {
    移动(路径(源)、路径(目标)、选项);
    }
    @凌驾
    公共布尔isSameFile(路径路径,路径路径2)
    抛出IOException
    {
    返回provider.isSameFile(路径(path),路径(path2));
    }
    @凌驾
    公共布尔值isHidden(路径)
    抛出IOException
    {
    返回provider.ishiden(路径(path));
    }
    @凌驾
    公共字符串getScheme()
    {
    返回provider.getScheme();
    }
    @凌驾
    公共路径getPath(URI)
    {
    返回provider.getPath(uri);
    }
    @凌驾
    公共文件系统getFileSystem(URI)
    {
    返回provi