Java 7 zip file system provider doesn't seem to accept spaces in URI

前端 未结 4 737
滥情空心
滥情空心 2020-12-18 18:35

I have been testing all possible variations and permutations, but I can\'t seem to construct a FileSystemProvider with the zip/jar scheme for a path (URI) that contains spac

4条回答
  •  再見小時候
    2020-12-18 19:12

    The jar: URIs should have the escaped zip-URI in its scheme-specific part, so your jar: URI is simply wrong - it should rightly be double-escaped, as the jar: scheme is composed of the host URI, !/ and the local path.

    However, this escaping is only implied and not expressed by the minimal URL "specification" in JarURLConnection. I agree however with the raised bug in JRE that it should still accept single-escaped, although that could lead to some strange edge-cases not being supported.

    As pointed out by tornike and evermean in another answer, the easiest is to do FileSystems.newFileSystem(path, null) - but this does not work when you want to pass and env with say "create"=true.

    Instead, create the jar: URI using the component-based constructor:

    URI jar = new URI("jar", path.toUri().toString(), null);
    

    This would properly encode the scheme-specific part.

    As a JUnit test, which also confirms that this is the escaping used when opening from a Path:

    @Test
    public void jarWithSpaces() throws Exception {
        Path path = Files.createTempFile("with several spaces", ".zip");
        Files.delete(path);
    
        // Will fail with FileSystemNotFoundException without env:
        //FileSystems.newFileSystem(path, null);
    
        // Neither does this work, as it does not double-escape:
        // URI jar = URI.create("jar:" + path.toUri().toASCIIString());                
    
        URI jar = new URI("jar", path.toUri().toString(), null);
        assertTrue(jar.toASCIIString().contains("with%2520several%2520spaces"));
    
        Map env = new HashMap<>();
        env.put("create", "true");
    
        try (FileSystem fs = FileSystems.newFileSystem(jar, env)) {
            URI root = fs.getPath("/").toUri();    
            assertTrue(root.toString().contains("with%2520several%2520spaces"));
        } 
        // Reopen from now-existing Path to check that the URI is
        // escaped in the same way
        try (FileSystem fs = FileSystems.newFileSystem(path, null)) {
            URI root = fs.getPath("/").toUri();
            //System.out.println(root.toASCIIString());
            assertTrue(root.toString().contains("with%2520several%2520spaces"));
        }
    }
    

    (I did a similar test with "with\u2301unicode\u263bhere" to check that I did not need to use .toASCIIString())

提交回复
热议问题