java 写入后如何清除 PrintWriter 的内容

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15593086/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 20:10:48  来源:igfitidea点击:

how to clear contents of a PrintWriter after writing

javaservletsprintwriter

提问by Java Player

Good evening, i want to know how to clear the data written to a PrintWriter, i.e. is it possible to remove the data from a PrintWriter after printing?

晚上好,我想知道如何清除写入 PrintWriter 的数据,即是否可以在打印后从 PrintWriter 中删除数据?

here in this servlet i print some text to the response and at the line denoted by # i want to remove all the previously printed data and print new stuff:

在此 servlet 中,我将一些文本打印到响应中,并在 # 表示的行中删除所有以前打印的数据并打印新内容:

protected void doGet(HttpServletRequest request,
        HttpServletResponse response) throws ServletException, IOException {
    PrintWriter out = response.getWriter();
    String uName = request.getParameter("uName");
    String uPassword = request.getParameter("uPassword");

    if (uName .equals("Islam")) {
        out.println("Valid-Name");
        if (uPassword !=null) {
            if (uPassword .equals("Islam")) {
                // # clear the writer from any printed data here
                out.println("Valid-password");
            } else {
                out.println("");
                out.println("InValid-password");
            }
        }
    } else {
        out.println("InValid-Name");

    }

}

Note: i tried out.flush() but the old printed text remains

注意:我尝试了 out.flush() 但旧的印刷文本仍然存在

采纳答案by Charles Forsythe

Create an in-memory PrintWriterusing a StringWriter. You can get the underlying buffer from the StringWriterand clear it if you need to.

创建一个内存PrintWriter使用StringWriterStringWriter如果需要,您可以从 中获取底层缓冲区并清除它。

StringWriter sr = new StringWriter();
PrintWriter w = new PrintWriter(sr);

w.print("Some stuff");
// Flush writer to ensure that it's not buffering anything
w.flush();
// clear stringwriter
sr.getBuffer().setLength(0);

w.print("New stuff");

// write to Servlet out
w.flush();
response.getWriter().print(sr.toString());

回答by Ramesh PVK

HttpServlteResponse.resetBuffer()will clear the buffered content. But yes, if the response is already flushed to the client it will throw IllegalStateException. Because it is illegal to clear after partial response is sent to the client.

HttpServlteResponse.resetBuffer()将清除缓冲的内容。但是是的,如果响应已经刷新到客户端,它将抛出IllegalStateException. 因为在向客户端发送部分响应后清除是非法的。

resetBuffer........

void resetBuffer()
Clears the content of the underlying buffer in the response without clearing headers or status code. If the response has been committed, this method throws an IllegalStateException.

重置缓冲区........

void resetBuffer()
清除响应中底层缓冲区的内容,而不清除标头或状态代码。如果已提交响应,则此方法将引发 IllegalStateException。

References:

参考:

Cause of Servlet's 'Response Already Committed'

Servlet 的“响应已提交”的原因

回答by timxor

What ended up working for me was to change the logic of how I was outputting my data.

最终对我有用的是改变我输出数据的逻辑。

enter image description here

在此处输入图片说明

This is the data structure I was outputting that stored the results of a search using the text from a html form as input.

这是我输出的数据结构,它存储了使用 html 表单中的文本作为输入的搜索结果。

private final TreeMap<String, ArrayList<SearchResult>> searchResults;

So I was iterating over the contents of this data structure and printing it out to html.

所以我正在迭代这个数据结构的内容并将其打印到 html 中。

public void writeSearchResultsToHtml(PrintWriter writer)
{
    try
    {
        JSONTreeWriter. writeSearchResultsToHtml(searchResults, writer);
    } catch (ArithmeticException | IllegalArgumentException | IOException | NoSuchElementException e)
    {
        System.err.println("Unable to write the search results builder to JSON to the file html.");
    }

    // clear results for next search otherwise
    // the next search will contain the previous
    // results, store them in history.
    searchResults.clear();
}

Clearing the data structure worked great given my servlet setup.

鉴于我的 servlet 设置,清除数据结构非常有效。

Here was my main serverlet loop logic:

这是我的主要 serverlet 循环逻辑:

public void startServer()
{
    // seed the database for testing
    crawler.startCrawl("http://cs.usfca.edu/~cs212/birds/birds.html");
    index.toJSON("index.json");

    // type of handler that supports sessions
    ServletContextHandler servletContext = null;

    // turn on sessions and set context
    servletContext = new ServletContextHandler(ServletContextHandler.SESSIONS);
    servletContext.setContextPath("/");
    servletContext.addServlet(ViewServlet.class, "/");

    // default handler for favicon.ico requests
    DefaultHandler defaultHandler = new DefaultHandler();
    defaultHandler.setServeIcon(true);

    ContextHandler defaultContext = new ContextHandler("/favicon.ico");
    defaultContext.setHandler(defaultHandler);

    // setup handler order
    HandlerList handlers = new HandlerList();
    handlers.setHandlers(new Handler[]{defaultContext, servletContext});

    openWebBrowser();

    // setup jetty server
    Server server = new Server(portNumber);
    server.setHandler(handlers);
    try
    {
        server.start();
        server.join();
    } catch (Exception e)
    {
        e.printStackTrace();
    }
}

回答by Costi Ciudatu

You can't do that with the original PrintWriteryou get from the response, as that's backed by the actual OutputStreamcorresponding to the client connection. What you write there goes right to the browser via the wire (after some buffering), so you can't "take it back".

您不能使用PrintWriter从响应中获得的原始数据来执行此操作,因为这是由OutputStream与客户端连接对应的实际数据支持的。你在那里写的东西通过线路直接进入浏览器(经过一些缓冲),所以你不能“收回”。

What you can do is write your message in some StringBuilderand once you know it's good to go, write it to the PrintWriter.

您可以做的是将您的消息写在一些中StringBuilder,一旦您知道可以走了,就将其写到PrintWriter.

If you want this logic to be applied in multiple places (transparently), you can consider writing a filter that wraps the original response in an HttpServletResponseWrapperwhich returns a "fake" OutputStreamor PrintWriterand performs this check prior to actually sending it over the wire.

如果您希望将此逻辑应用于多个地方(透明地),您可以考虑编写一个过滤器,将原始响应包装在一个HttpServletResponseWrapper返回“假”OutputStreamPrintWriter并在实际通过网络发送之前执行此检查的 。

public class CensorshipFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        CensorshipResponseWrapper wrapper = new CensorshipResponseWrapper(httpServletResponse);
        chain.doFilter(request, wrapper);
        String output = wrapper.sw.toString();
        if ( output.contains("Some forbidden pattern") ) { // your check goes here
            // throw exception or whatever
        } else { // write the whole thing
            httpServletResponse.getWriter().write(output);
        }
    }

    @Override
    public void destroy() {
    }

    static class CensorshipResponseWrapper extends HttpServletResponseWrapper {
        private final StringWriter sw = new StringWriter();

        public CensorshipResponseWrapper(HttpServletResponse response) {
            super(response);
        }

        @Override
        public ServletOutputStream getOutputStream() throws IOException {
            // you may also fake the output stream, if some of your servlets use this method
            return super.getOutputStream();
        }

        @Override
        public PrintWriter getWriter() throws IOException {
            return new PrintWriter(sw);
        }
    }
}