On 2015-01-04 11:06, Alan Bateman wrote:
On 02/01/2015 15:38, Claes Redestad wrote:
Hi,

this is a proposal to resolve concerns that PrintWriter/BufferedWriter behave inconsistently with j.u.Formatter when setting the line.separator property to override
system-appropriate line breaks.

Instead of providing a set of new constructors, I propose to simply add a new default method j.l.Appendable#lineSeparator, which by default delegates to System.lineSeparator(). This allows classes such as PrintWriter/BufferedWriter to provide overrides which
communicate to j.u.Formatter their intended behavior.
In the bug report then I assume the inconsistency only arises because the test case attempts to change the line separator in the main method, which is too late. It should work if set on the command-line but this of course sets it system-wide.

Right, the PrintWriter inconsistency detailed:
- methods format/printf uses j.u.Formatter, which uses System.lineSeparator() internally if it encounters an "%n" in the format string. Only responds to when changing line.separator on
command-line or similar.
- methods println and newLine use the PrintWriter internal lineSeparator value evaluated at
object creation time:

    public PrintWriter(Writer out,
                       boolean autoFlush) {
        super(out);
        this.out = out;
        this.autoFlush = autoFlush;
        lineSeparator = java.security.AccessController.doPrivileged(
            new sun.security.action.GetPropertyAction("line.separator"));
    }

This leads to hacks existing in the wild which sets line.separator before creating the PrintWriter, as exemplified here: http://stackoverflow.com/questions/1014287/is-there-a-way-to-make-printwriter-output-to-unix-format

Removing this functionality could break compatibility with some applications where developers are intentionally changing the line.separator, while it'd be nice if there was a better way to facilitate
this, which I think my proposal would allow with minimal


Your proposal to add a lineSeperator() method to Appendable would allow for customization but I'm not sure that it's the right place (as Appendable is a very general interface and would require every Appendable implementation that writes lines to be updated to make use of the new method).

Yes, this can seem an awkward place to add this method, but the only place where we'd be able to as easily make java.util.Formatter use the custom lineSeparator, without which we wouldn't be able to resolve the inconsistency above nor provide a more convenient way for developers
to avoid the line.separator hack.

However, since Appendable is defined rather strictly-coupled with java.util.Formatter ("The Appendable interface must be implemented by any class whose instances are intended to receive formatted output from a java.util.Formatter.") and Formatter provides a higher-order mechanism to print new-lines ("%n") to the Appendable, it doesn't feel entirely arbitrary that the lineSeparator behavior should be
accessible via Appendable.


An alternative to consider is adding the notion of lines to java.io.Writer and update it to define newLine() and lineSeperator() methods (i.e. move the BufferWriter::newLine method up to Writer). It's a bit of extra work to update BufferedWriter's spec, adjust a few things in PrintWriter/PrintStream, and special-case Writers in Formatter but something to consider.

I need to think about what that would mean, and especially how to solve it on the Formatter side. I worry shoehorning Writer or upcasts into Formatter might be more complex that it's worth.
Any ideas?

/Claes


-Alan

Reply via email to