Search code examples
javaprintwriterauto-indent

Why doesn't my TabbedPrintWriter work?


I am writing a java decompiler. To give the output a nice indent, I have decided to write a class called TabbedPrintWriter to automatically tabify the output appropriately. Here's the code:

import java.io.OutputStream;
import java.io.PrintWriter;

public class TabbedPrintWriter extends PrintWriter {
    private static int indentAmount = 4;
    private int indent = 0;
    public TabbedPrintWriter(OutputStream out) {
        super(out);
    }

    public TabbedPrintWriter(OutputStream out, boolean autoFlush) {
        super(out, autoFlush);
    }

    @Override
    public void println() {
        super.println();
        for (int i = 0; i <= indentAmount * indent; i++) {
            super.write(' ');
        }
    }

    public void indent() {
        indent++;
    }

    public void unindent() {
        indent--;
    }

}

I also wrote a test class to test this:

public class TabbedPrintWriterTest {

    public static void main(String[] args) {
        TabbedPrintWriter writer = new TabbedPrintWriter(System.out, true);
        writer.println("Hello");
        writer.indent();
        writer.println("Goodbye");
    }

}

If you look at the code, each indent level should be four spaces. However, if I run this, I get this output:

Hello
 Goodbye

Yes, that's right. Only one space.

Why is this?


Solution

  • After a rewrite of code and some debugging, I finally managed to get this to work:

    public class TabbedPrintWriter extends PrintWriter {
    
        private static int indentAmount = 4;
        private int indent = 0;
        private StringBuilder line = new StringBuilder();
    
        public TabbedPrintWriter(OutputStream out) {
            super(out);
        }
    
        public TabbedPrintWriter(OutputStream out, boolean autoFlush) {
            super(out, autoFlush);
        }
    
        @Override
        public void println() {
            for (int i = 0; i < indentAmount * indent; i++)
                line.insert(0, ' ');
            super.write(line.toString(), 0, line.length());
            line = new StringBuilder();
            super.println();
        }
    
        @Override
        public void write(int c) {
            line.append((char) c);
        }
    
        @Override
        public void write(String s, int off, int len) {
            line.append(s, off, len);
        }
    
        @Override
        public void write(char[] buf, int off, int len) {
            line.append(buf, off, len);
        }
    
        public void indent() {
            indent++;
        }
    
        public void unindent() {
            indent--;
        }
    }
    

    Basically, I do line buffering and insert indentation prior to printing out the line. Now that it is working, I will not be needing the help of the community, so the primary reason is to make sure nobody gets distracted trying to answer a question that doesn't need answering. And to spread the word of a working tabbed print writer.