【问题标题】:how to clear contents of a PrintWriter after writing写入后如何清除 PrintWriter 的内容
【发布时间】:2013-03-23 22:59:21
【问题描述】:

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

在这个 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");

    }

}

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

【问题讨论】:

  • flush 应该可以解决问题,然后是 close。
  • Servlet 的规范提供了一种方法来做到这一点。请看下面的答案

标签: java servlets printwriter


【解决方案1】:

使用StringWriter 创建内存中的PrintWriter。您可以从StringWriter 获取底层缓冲区并在需要时将其清除。

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());

【讨论】:

  • Servlet 的规范提供了一种方法来做到这一点。请看下面的答案。
  • 这种方法并不总是有效。没有标准的方法来保证 Servlet PrintWriter 底层缓冲区的大小;事实上,它没有义务提供一个。这种方法总是有效的。
  • 只要知道 Servlet 规范的内容,它就会一直工作。
  • Servlet 规范说,当您在 PrintWriter 中溢出缓冲区时,可以提交响应。您不知道缓冲区大小是多少,实际上它不可能是 0 字节。这如何帮助您“始终有效”?
  • 您可以随时设置所需的缓冲区大小。即使您使用自己的 PrintWriter,也只能在一定程度上缓冲。什么不能设置为响应缓冲区大小。
【解决方案2】:

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

resetBuffer........

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

参考资料:

Cause of Servlet's 'Response Already Committed'

【讨论】:

    【解决方案3】:

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

    您可以做的是在StringBuilder 中写下您的信息,一旦您知道可以使用,请将其写到PrintWriter

    如果您希望在多个地方(透明地)应用此逻辑,您可以考虑编写一个过滤器,将原始响应包装在 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);
            }
        }
    }
    

    【讨论】:

    • 关于第二种通用​​方法(响应包装器),或者如何使用 StringBuilder ?
    • 关于第二种通用​​方法(响应包装器)
    【解决方案4】:

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

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

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

    所以我正在迭代这个数据结构的内容并将其打印到 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();
    }
    

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

    这是我的主要 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();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-05-12
      • 2010-12-19
      • 2019-11-13
      • 1970-01-01
      • 1970-01-01
      • 2014-02-01
      • 2018-08-31
      相关资源
      最近更新 更多