20

I am generating dynamic page using JSP, I want to save this dynamically generated complete page in file as archive.

In JSP, everything is written to PrintWriter out = response.getWriter();

At the end of page, before sending response to client I want to save this page, either in file or in buffer as string for later treatment.

How can I save Printwriter content or convert to String?

adarshr
  • 57,189
  • 21
  • 133
  • 158
superzoom
  • 399
  • 1
  • 3
  • 7
  • please check the answers for the following question. http://stackoverflow.com/questions/2010990/how-do-you-return-a-json-object-from-a-java-servlet – Raj Feb 10 '12 at 11:13
  • Thanks Raj, but this not what I am looking for, client will see normal html, but on server side, script will create local copy and write in file. – superzoom Feb 10 '12 at 11:21
  • possible duplicate of [How to log response content from a java web server](http://stackoverflow.com/questions/8933054/how-to-log-response-content-from-a-java-web-server) – BalusC Feb 10 '12 at 13:37

7 Answers7

44

To get a string from the output of a PrintWriter, you can pass a StringWriter to a PrintWriter via the constructor:

@Test
public void writerTest(){
    StringWriter out    = new StringWriter();
    PrintWriter  writer = new PrintWriter(out);

    // use writer, e.g.:
    writer.print("ABC");
    writer.print("DEF");

    writer.flush(); // flush is really optional here, as Writer calls the empty StringWriter.flush
    String result = out.toString();

    assertEquals("ABCDEF", result);
}
weston
  • 51,132
  • 20
  • 132
  • 192
11

Why not use StringWriter instead? I think this should be able to provide what you need.

So for example:

StringWriter strOut = new StringWriter();
...
String output = strOut.toString();
System.out.println(output);
GreenGiant
  • 4,226
  • 1
  • 40
  • 69
Alvin Bunk
  • 7,106
  • 3
  • 26
  • 40
  • because it's not a subclass of PrintWriter so it doesn't interchangeable in places we type is defined as PrintWriter instead of Writer – Yura Jul 23 '20 at 10:51
7

It will depend on: how the PrintWriter is constructed and then used.

If the PrintWriter is constructed 1st and then passed to code that writes to it, you could use the Decorator pattern that allows you to create a sub-class of Writer, that takes the PrintWriter as a delegate, and forwards calls to the delegate, but also maintains a copy of the content that you can then archive.

public class DecoratedWriter extends Writer
{
   private final Writer delegate;

   private final StringWriter archive = new StringWriter();

   //pass in the original PrintWriter here
   public DecoratedWriter( Writer delegate )
   {
      this.delegate = delegate;
   }

   public String getForArchive()
   { 
      return this.archive.toString();
   } 

   public void write( char[] cbuf, int off, int len ) throws IOException
   {
      this.delegate.write( cbuf, off, len );
      this.archive.write( cbuf, off, len );
   }

   public void flush() throws IOException
   {
      this.delegate.flush();
      this.archive.flush();

   } 

   public void close() throws IOException
   {
      this.delegate.close();
      this.archive.close();
   }
}
cdc
  • 2,224
  • 2
  • 13
  • 12
1

You cannot get it with just your PrintWriter object. It flushes the data, and does not hold any content within itself. This isn't the object you should be looking at to get the entire string,

Navneeth G
  • 7,005
  • 1
  • 12
  • 17
  • Thanks Navneeth Gopalakrishnan, if I cant use Printwriter, ,then what option I have available ? What about response object? Because everything is going through response to client!!! – superzoom Feb 10 '12 at 11:18
  • 1
    You can write things you want to write into a StringWriter and finally when everything is done, you can write it to the reponse's writer too. In that way you have the data you have written which can be used for any other purposes. – Navneeth G Feb 10 '12 at 11:22
  • When I mean write, I meant, flush the contents in the StringWriter to your `response.getWriter()` too. – Navneeth G Feb 10 '12 at 11:23
0

Along similar lines to what cdc is doing - you can extend PrintWriter and then create and pass around an instance of this new class.

Call getArchive() to get a copy of the data that's passed through the writer.

public class ArchiveWriter extends PrintWriter {
    private StringBuilder data = new StringBuilder();

    public ArchiveWriter(Writer out) {
        super(out);
    }

    public ArchiveWriter(Writer out, boolean autoFlush) {
        super(out, autoFlush);
    }

    public ArchiveWriter(OutputStream out) {
        super(out);
    }

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

    public ArchiveWriter(String fileName) throws FileNotFoundException {
        super(fileName);
    }

    public ArchiveWriter(String fileName, String csn) throws FileNotFoundException, UnsupportedEncodingException {
        super(fileName, csn);
    }

    public ArchiveWriter(File file) throws FileNotFoundException {
        super(file);
    }

    public ArchiveWriter(File file, String csn) throws FileNotFoundException, UnsupportedEncodingException {
        super(file, csn);
    }

    @Override
    public void write(char[] cbuf, int off, int len) {
        super.write(cbuf, off,len);
        data.append(cbuf, off, len);
    }

    @Override
    public void write(String s, int off, int len) {
        super.write(s, off,len);
        data.append(s, off, len);
    }

    public String getArchive() {
        return data.toString();
    }
}
weston
  • 51,132
  • 20
  • 132
  • 192
Will Calderwood
  • 3,878
  • 2
  • 31
  • 55
0

The best way I think is prepare your response in other object like StringBuffer, and fush its content to the response, and after save the content stored in that variable to the file.

Rigoni
  • 302
  • 5
  • 15
-1

This helped me: for obtaining a SOAP-able object as XML string.

JAXBContext jc = JAXBContext.newInstance(o.getClass());
Marshaller m = jc.createMarshaller();
StringWriter writer = new StringWriter();
m.marshal( o, new PrintWriter(writer) );
return writer.toString();
Jubz
  • 147
  • 1
  • 10