Index: /trunk/src/org/openstreetmap/josm/data/Preferences.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/Preferences.java	(revision 9822)
+++ /trunk/src/org/openstreetmap/josm/data/Preferences.java	(revision 9823)
@@ -58,4 +58,5 @@
 import org.openstreetmap.josm.data.preferences.MapListSetting;
 import org.openstreetmap.josm.data.preferences.PreferencesReader;
+import org.openstreetmap.josm.data.preferences.PreferencesWriter;
 import org.openstreetmap.josm.data.preferences.Setting;
 import org.openstreetmap.josm.data.preferences.SettingVisitor;
@@ -538,5 +539,6 @@
         try (PrintWriter out = new PrintWriter(new OutputStreamWriter(
                 new FileOutputStream(prefFile + "_tmp"), StandardCharsets.UTF_8), false)) {
-            out.print(toXML(settings, false, defaults));
+            PreferencesWriter writer = new PreferencesWriter(out, false, defaults);
+            writer.write(settings);
         }
 
@@ -576,6 +578,6 @@
         File pref = getPreferenceFile();
         PreferencesReader.validateXML(pref);
-        PreferencesReader reader = new PreferencesReader(false);
-        reader.fromXML(pref);
+        PreferencesReader reader = new PreferencesReader(pref, false);
+        reader.parse();
         settingsMap.clear();
         settingsMap.putAll(reader.getSettings());
@@ -596,6 +598,6 @@
         File def = getDefaultsCacheFile();
         PreferencesReader.validateXML(def);
-        PreferencesReader reader = new PreferencesReader(true);
-        reader.fromXML(def);
+        PreferencesReader reader = new PreferencesReader(def, true);
+        reader.parse();
         defaultsMap.clear();
         long minTime = System.currentTimeMillis() / 1000 - MAX_AGE_DEFAULT_PREFERENCES;
@@ -611,8 +613,9 @@
      * @param in XML reader
      * @throws XMLStreamException if any XML stream error occurs
-     */
-    public void fromXML(Reader in) throws XMLStreamException {
-        PreferencesReader reader = new PreferencesReader(false);
-        reader.fromXML(in);
+     * @throws IOException if any I/O error occurs
+     */
+    public void fromXML(Reader in) throws XMLStreamException, IOException {
+        PreferencesReader reader = new PreferencesReader(in, false);
+        reader.parse();
         settingsMap.clear();
         settingsMap.putAll(reader.getSettings());
@@ -1399,107 +1402,4 @@
     }
 
-    private static class SettingToXml implements SettingVisitor {
-        private final StringBuilder b;
-        private final boolean noPassword;
-        private final boolean defaults;
-        private String key;
-
-        SettingToXml(StringBuilder b, boolean noPassword, boolean defaults) {
-            this.b = b;
-            this.noPassword = noPassword;
-            this.defaults = defaults;
-        }
-
-        public void setKey(String key) {
-            this.key = key;
-        }
-
-        private void addTime(Setting setting) {
-            if (defaults) {
-                Long time = setting.getTime();
-                if (time == null) throw new IllegalStateException();
-                b.append("' time='").append(time);
-            }
-        }
-
-        @Override
-        public void visit(StringSetting setting) {
-            if (noPassword && "osm-server.password".equals(key))
-                return; // do not store plain password.
-            b.append("  <tag key='");
-            b.append(XmlWriter.encode(key));
-            addTime(setting);
-            if (setting.getValue() != null) {
-                b.append("' value='");
-                b.append(XmlWriter.encode(setting.getValue()));
-                b.append("'/>\n");
-            } else if (defaults) {
-                b.append("' xsi:nil='true'/>\n");
-            } else {
-                throw new NullPointerException();
-            }
-        }
-
-        @Override
-        public void visit(ListSetting setting) {
-            b.append("  <list key='").append(XmlWriter.encode(key));
-            addTime(setting);
-            if (setting.getValue() != null) {
-                b.append("'>\n");
-                for (String s : setting.getValue()) {
-                    b.append("    <entry value='").append(XmlWriter.encode(s)).append("'/>\n");
-                }
-                b.append("  </list>\n");
-            } else if (defaults) {
-                b.append("' xsi:nil='true'/>\n");
-            } else {
-                throw new NullPointerException();
-            }
-        }
-
-        @Override
-        public void visit(ListListSetting setting) {
-            b.append("  <lists key='").append(XmlWriter.encode(key));
-            addTime(setting);
-            if (setting.getValue() != null) {
-                b.append("'>\n");
-                for (List<String> list : setting.getValue()) {
-                    b.append("    <list>\n");
-                    for (String s : list) {
-                        b.append("      <entry value='").append(XmlWriter.encode(s)).append("'/>\n");
-                    }
-                    b.append("    </list>\n");
-                }
-                b.append("  </lists>\n");
-            } else if (defaults) {
-                b.append("' xsi:nil='true'/>\n");
-            } else {
-                throw new NullPointerException();
-            }
-        }
-
-        @Override
-        public void visit(MapListSetting setting) {
-            b.append("  <maps key='").append(XmlWriter.encode(key));
-            addTime(setting);
-            if (setting.getValue() != null) {
-                b.append("'>\n");
-                for (Map<String, String> struct : setting.getValue()) {
-                    b.append("    <map>\n");
-                    for (Entry<String, String> e : struct.entrySet()) {
-                        b.append("      <tag key='").append(XmlWriter.encode(e.getKey()))
-                         .append("' value='").append(XmlWriter.encode(e.getValue())).append("'/>\n");
-                    }
-                    b.append("    </map>\n");
-                }
-                b.append("  </maps>\n");
-            } else if (defaults) {
-                b.append("' xsi:nil='true'/>\n");
-            } else {
-                throw new NullPointerException();
-            }
-        }
-    }
-
     /**
      * Returns XML describing these preferences.
@@ -1520,19 +1420,11 @@
      */
     public String toXML(Collection<Entry<String, Setting<?>>> settings, boolean nopass, boolean defaults) {
-        String rootElement = defaults ? "preferences-defaults" : "preferences";
-        StringBuilder b = new StringBuilder("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<")
-                .append(rootElement).append(" xmlns='")
-                .append(Main.getXMLBase()).append("/preferences-1.0'");
-        if (defaults) {
-            b.append(" xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'");
-        }
-        b.append(" version='").append(Version.getInstance().getVersion()).append("'>\n");
-        SettingToXml toXml = new SettingToXml(b, nopass, defaults);
-        for (Entry<String, Setting<?>> e : settings) {
-            toXml.setKey(e.getKey());
-            e.getValue().visit(toXml);
-        }
-        b.append("</").append(rootElement).append(">\n");
-        return b.toString();
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        PreferencesWriter prefWriter = new PreferencesWriter(pw, nopass, defaults);
+        prefWriter.write(settings);
+        sw.flush();
+        StringBuffer sb = sw.getBuffer();
+        return sb.toString();
     }
 
Index: /trunk/src/org/openstreetmap/josm/data/preferences/PreferencesReader.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/preferences/PreferencesReader.java	(revision 9822)
+++ /trunk/src/org/openstreetmap/josm/data/preferences/PreferencesReader.java	(revision 9823)
@@ -41,6 +41,8 @@
 
     private final SortedMap<String, Setting<?>> settings = new TreeMap<>();
+    private XMLStreamReader parser;
     private int version = 0;
-    private XMLStreamReader parser;
+    private Reader reader;
+    private File file;
 
     private final boolean defaults;
@@ -48,9 +50,27 @@
     /**
      * Constructs a new {@code PreferencesReader}.
+     * @param file the file
      * @param defaults true when reading from the cache file for default preferences,
      * false for the regular preferences config file
-     */
-    public PreferencesReader(boolean defaults) {
+     * @throws IOException if any I/O error occurs
+     * @throws XMLStreamException if any XML stream error occurs
+     */
+    public PreferencesReader(File file, boolean defaults) throws IOException, XMLStreamException {
         this.defaults = defaults;
+        this.reader = null;
+        this.file = file;
+    }
+
+    /**
+     * Constructs a new {@code PreferencesReader}.
+     * @param reader the {@link Reader}
+     * @param defaults true when reading from the cache file for default preferences,
+     * false for the regular preferences config file
+     * @throws XMLStreamException if any XML stream error occurs
+     */
+    public PreferencesReader(Reader reader, boolean defaults) throws XMLStreamException {
+        this.defaults = defaults;
+        this.reader = reader;
+        this.file = null;
     }
 
@@ -82,26 +102,4 @@
 
     /**
-     * Parse preferences XML.
-     * @param f the file
-     * @throws IOException if any I/O error occurs
-     * @throws XMLStreamException if any XML stream error occurs
-     */
-    public void fromXML(File f) throws IOException, XMLStreamException {
-        try (BufferedReader in = Files.newBufferedReader(f.toPath(), StandardCharsets.UTF_8)) {
-            fromXML(in);
-        }
-    }
-
-    /**
-     * Parse preferences XML.
-     * @param in the {@link Reader}
-     * @throws XMLStreamException if any XML stream error occurs
-     */
-    public void fromXML(Reader in) throws XMLStreamException {
-        this.parser = XMLInputFactory.newInstance().createXMLStreamReader(in);
-        parse();
-    }
-
-    /**
      * Return the parsed preferences as a settings map
      * @return the parsed preferences as a settings map
@@ -120,5 +118,18 @@
     }
 
-    private void parse() throws XMLStreamException {
+
+    public void parse() throws XMLStreamException, IOException {
+        if (reader != null) {
+            this.parser = XMLInputFactory.newInstance().createXMLStreamReader(reader);
+            doParse();
+        } else {
+            try (BufferedReader in = Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8)) {
+                this.parser = XMLInputFactory.newInstance().createXMLStreamReader(in);
+                doParse();
+            }
+        }
+    }
+
+    private void doParse() throws XMLStreamException {
         int event = parser.getEventType();
         while (true) {
Index: /trunk/src/org/openstreetmap/josm/data/preferences/PreferencesWriter.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/preferences/PreferencesWriter.java	(revision 9823)
+++ /trunk/src/org/openstreetmap/josm/data/preferences/PreferencesWriter.java	(revision 9823)
@@ -0,0 +1,143 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.data.preferences;
+
+import java.io.PrintWriter;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.Version;
+import org.openstreetmap.josm.io.XmlWriter;
+
+/**
+ * Write preferences to XML.
+ */
+public class PreferencesWriter extends XmlWriter implements SettingVisitor {
+    private final boolean noPassword;
+    private final boolean defaults;
+    private String key;
+
+    /**
+     * Construct new {@code PreferencesWriter}.
+     * @param out the {@link PrintWriter}
+     * @param noPassword if password must be excluded
+     * @param defaults true, if default values are converted to XML, false for
+     * regular preferences
+     */
+    public PreferencesWriter(PrintWriter out, boolean noPassword, boolean defaults) {
+        super(out);
+        this.noPassword = noPassword;
+        this.defaults = defaults;
+    }
+
+    /**
+     * Write preferences.
+     *
+     * @param settings preferences settings to write
+     */
+    public void write(Collection<Map.Entry<String, Setting<?>>> settings) {
+        out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+        String rootElement = defaults ? "preferences-defaults" : "preferences";
+        out.write(String.format("<%s xmlns='%s/preferences-1.0'", rootElement, Main.getXMLBase()));
+        if (defaults) {
+            out.write(" xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'");
+        }
+        out.write(String.format(" version='%d'>\n", Version.getInstance().getVersion()));
+        for (Map.Entry<String, Setting<?>> e : settings) {
+            setKey(e.getKey());
+            e.getValue().visit(this);
+        }
+        out.write(String.format("</%s>\n", rootElement));
+    }
+
+    private void setKey(String key) {
+        this.key = key;
+    }
+
+    private void addTime(Setting setting) {
+        if (defaults) {
+            Long time = setting.getTime();
+            if (time == null) throw new IllegalStateException();
+            out.write("' time='" + time);
+        }
+    }
+
+    @Override
+    public void visit(StringSetting setting) {
+        if (noPassword && "osm-server.password".equals(key))
+            return; // do not store plain password.
+        out.write("  <tag key='");
+        out.write(XmlWriter.encode(key));
+        addTime(setting);
+        if (setting.getValue() != null) {
+            out.write("' value='");
+            out.write(XmlWriter.encode(setting.getValue()));
+            out.write("'/>\n");
+        } else if (defaults) {
+            out.write("' xsi:nil='true'/>\n");
+        } else {
+            throw new NullPointerException();
+        }
+    }
+
+    @Override
+    public void visit(ListSetting setting) {
+        out.write("  <list key='" + XmlWriter.encode(key));
+        addTime(setting);
+        if (setting.getValue() != null) {
+            out.write("'>\n");
+            for (String s : setting.getValue()) {
+                out.write("    <entry value='" + XmlWriter.encode(s) + "'/>\n");
+            }
+            out.write("  </list>\n");
+        } else if (defaults) {
+            out.write("' xsi:nil='true'/>\n");
+        } else {
+            throw new NullPointerException();
+        }
+    }
+
+    @Override
+    public void visit(ListListSetting setting) {
+        out.write("  <lists key='" + XmlWriter.encode(key));
+        addTime(setting);
+        if (setting.getValue() != null) {
+            out.write("'>\n");
+            for (List<String> list : setting.getValue()) {
+                out.write("    <list>\n");
+                for (String s : list) {
+                    out.write("      <entry value='" + encode(s) + "'/>\n");
+                }
+                out.write("    </list>\n");
+            }
+            out.write("  </lists>\n");
+        } else if (defaults) {
+            out.write("' xsi:nil='true'/>\n");
+        } else {
+            throw new NullPointerException();
+        }
+    }
+
+    @Override
+    public void visit(MapListSetting setting) {
+        out.write("  <maps key='" + encode(key));
+        addTime(setting);
+        if (setting.getValue() != null) {
+            out.write("'>\n");
+            for (Map<String, String> struct : setting.getValue()) {
+                out.write("    <map>\n");
+                for (Map.Entry<String, String> e : struct.entrySet()) {
+                    out.write(String.format("      <tag key='%s' value='%s'/>\n", encode(e.getKey()), encode(e.getValue())));
+                }
+                out.write("    </map>\n");
+            }
+            out.write("  </maps>\n");
+        } else if (defaults) {
+            out.write("' xsi:nil='true'/>\n");
+        } else {
+            throw new NullPointerException();
+        }
+    }
+
+}
Index: /trunk/src/org/openstreetmap/josm/tools/date/DateUtils.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/date/DateUtils.java	(revision 9822)
+++ /trunk/src/org/openstreetmap/josm/tools/date/DateUtils.java	(revision 9823)
@@ -312,5 +312,5 @@
      * @param zone the timezone to use
      */
-    protected static void setTimeZone(TimeZone zone) {
+    protected static synchronized void setTimeZone(TimeZone zone) {
         calendarLocale.setTimeZone(zone);
     }
