Transformer library that comes with Java converts spaces in file paths to %20

纵然是瞬间 提交于 2019-12-21 12:40:16

问题


Here is a test application that writes out XML Files.

Why are the spaces in my path being converted to %20?

public class XmlTest
{
    public static void main(String[] args)
    {
        String filename = "C:\\New Folder\\test.xml";
        try {
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
            Document doc = docBuilder.newDocument();
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
            DOMSource source = new DOMSource(doc);

            File xmlFile = new File(filename);
            if (xmlFile.exists())
            {
                xmlFile.delete();
            }
            StreamResult result = new StreamResult(xmlFile);
            transformer.transform(source, result);

        }
        catch (ParserConfigurationException ex)
        {
            ex.printStackTrace();
        }
        catch (TransformerException tfe)
        {
            tfe.printStackTrace();
        }
    }
}

Stacktrace:

java.io.FileNotFoundException: C:\New%20Folder\test.xml (The system cannot find the path specified)
    at java.io.FileOutputStream.open(Native Method)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:179)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:70)
    at org.apache.xalan.transformer.TransformerIdentityImpl.createResultContentHandler(TransformerIdentityImpl.java:287)
    at org.apache.xalan.transformer.TransformerIdentityImpl.transform(TransformerIdentityImpl.java:330)
    at avm.trans.xml.XmlTest.main(XmlTest.java:52)

回答1:


Try to change this line:

StreamResult result = new StreamResult(xmlFile);

into this:

StreamResult result = new StreamResult(new FileOutputStream(xmlFile));

I have no Idea, why the filename is handled as an URL.




回答2:


Following from @ChristianKuetbach's answer, it would seem like the argument passed to the StreamResult constructor determines how it will be handled.

From the Oracle docs

public StreamResult(String systemId)  
    Construct a StreamResult from a URL.  
Parameters:  
    systemId - Must be a String that conforms to the URI syntax.

public StreamResult(File f)
   Construct a StreamResult from a File.
Parameters:
   f - Must a non-null File reference.

So initially, I was passing a String path, and so presumably the StreamResult decided to take the initiative to encode it automatically, rather than assuming it is "a String that comforms to the URI syntax".

As a result, passing in a File object told it to handle it as a file path instead of a URL and therefore spaces (and other special characters) were not encoded.




回答3:


This problem might also occur in cases of paths containing special characters, for which the first answer isn't helping pretty much(with the conversion, that is). For example, in my case the path of my file contained the char "`" that was automatically translated into "%60".

I solved my problem by changing the code line:

StreamResult result = new StreamResult(xmlFile);

result = D:/Work/.../%60Projects/.../xmlFile.xml

into code lines:

StreamResult result = new StreamResult(xmlFile);
result.setSystemId(URLDecoder.decode(xmlFile.toURI().toURL().toString(), "UTF-8"));

result = D:/Work/.../`Projects/.../xmlFile.xml

This overrides the URL encoding problem that's implemented by default within the StreamResult class.



来源:https://stackoverflow.com/questions/20434510/transformer-library-that-comes-with-java-converts-spaces-in-file-paths-to-20

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!