Закрытие входных потоков? [Дубликат]

Это происходит из-за того, что неявный фид строки, также известный как символ новой строки \n, добавляется ко всем пользовательским вводам терминала, поскольку он сообщает потоку начать новую строку. Вы можете смело учитывать это, используя std::getline при проверке нескольких строк ввода пользователя. Поведение по умолчанию std::getline будет читать все до и включая символ новой строки \n из объекта входного потока, который в этом случае является std::cin.

#include 
#include 

int main()
{
    std::string name;
    std::string state;

    if (std::getline(std::cin, name) && std::getline(std::cin, state))
    {
        std::cout << "Your name is " << name << " and you live in " << state;
    }
    return 0;
}
Input:

"John"
"New Hampshire"

Output:

"Your name is John and you live in New Hampshire"
blockquote >

78
задан Steven Huwig 21 July 2009 в 14:27
поделиться

5 ответов

Обычно вы не должны закрывать поток. Контейнер сервлета автоматически закрывает поток после завершения сервлета как часть жизненного цикла запроса сервлета.

Например, если вы закрыли поток, он не будет доступен, если вы внедрили Фильтр .

Сказав все это, если вы его закрываете ничего плохого не произойдет, если вы не пытаетесь использовать его снова.

EDIT: другая ссылка фильтра

EDIT2: adrian.tarau is correct в том случае, если вы хотите изменить ответ после того, как сервлет выполнил свою задачу, вы должны создать оболочку, расширяющую HttpServletResponseWrapper, и буферизировать вывод. Это необходимо для того, чтобы выход выводился непосредственно клиенту, но также позволяет защитить, если сервлет закрывает поток, согласно этой выдержке (выделение мое):

Фильтр, который изменяет ответ должен обычно захватывать ответ до того, как он будет возвращен клиенту. Способ сделать это - передать сервлет, который генерирует ответ на резервный поток. Резервный поток не позволяет сервлету закрывать исходный поток ответа при его завершении и позволяет фильтру изменять ответ сервлета.

Статья

Из этой официальной статьи Sun можно сделать вывод, что закрытие выходного потока сервлета является нормальным явлением, но не является обязательным.

81
ответ дан Nemi 21 August 2018 в 03:51
поделиться
  • 1
    Это верно. Следует отметить, что в некоторых случаях вам может понадобиться очистить поток, и это вполне допустимо. – toluju 21 July 2009 в 19:45
  • 2
    Существует еще один побочный эффект закрытия писателя. Вы также не сможете установить код состояния через response.setStatus после его закрытия. – che javara 15 April 2013 в 22:40
  • 3
    Следуйте этому совету. Это сэкономит вам много боли. Я бы не flush (), если вы не знаете, почему вы это делаете - вы должны позволить буферизации дескриптора контейнера. – Hal50000 2 October 2014 в 23:11

Вы должны закрыть поток, код становится более чистым, так как вы вызываете getOutputStream (), и поток не передается вам в качестве параметра, когда обычно вы просто используете его и не пытаетесь его закрыть. API-интерфейс Servlet не утверждает, что, если выходной поток может быть закрыт или не должен быть закрыт, в этом случае вы можете безопасно закрыть поток, любой контейнер там позаботится о закрытии потока, если он не был закрыт сервлетом.

Вот метод close () в Jetty, они закрывают поток, если он не закрыт.

public void close() throws IOException
    {
        if (_closed)
            return;

        if (!isIncluding() && !_generator.isCommitted())
            commitResponse(HttpGenerator.LAST);
        else
            flushResponse();

        super.close();
    }

Также как разработчик фильтра вы не должны предполагать, что OutputStream не закрывается, вы всегда должны передавать другой OutputStream, если хотите изменить содержимое после того, как сервлет выполнил свою работу.

EDIT: я всегда закрываю поток, и у меня не было никаких проблем с Tomcat / Jetty. Я не думаю, что у вас возникнут проблемы с контейнером, старым или новым.

3
ответ дан adrian.tarau 21 August 2018 в 03:51
поделиться
  • 1
    msgstr "Вы должны закрыть поток, код будет более чистым ... & quot; - Для меня код, наложенный на .close (), выглядит менее чистым, чем без кода, особенно если нет .close () - это то, что этот вопрос пытается определить. – Steven Huwig 21 July 2009 в 17:00
  • 2
    yep, но красота приходит после :) Во всяком случае, поскольку API не ясен, я бы предпочел закрыть его, код выглядит последовательным, как только вы запросите OutputStream, вы должны закрыть его, если API не говорит «не закрывать его». – adrian.tarau 21 July 2009 в 20:17
  • 3
    Я не думаю, что закрытие потока вывода в моем собственном коде - хорошая практика. Это задача контейнера. – JimHawkins 23 February 2016 в 15:48
  • 4
    get * не создает поток, это не производитель. Вы не должны закрывать его, контейнер должен это сделать. – dmatej 11 August 2016 в 10:18

Общее правило заключается в следующем: если вы открыли поток, вы должны закрыть его. Если вы этого не сделали, вы не должны. Убедитесь, что код симметричен.

В случае HttpServletResponse он немного менее четкий, так как это не очевидно, если вызов getOutputStream() - это операция, которая открывает поток. Джавадок просто говорит, что это «Returns a ServletOutputStream»; аналогично для getWriter(). В любом случае, ясно, что HttpServletResponse «владеет» потоком / писателем, и он (или контейнер) отвечает за его закрытие снова.

Итак, чтобы ответить на ваш вопрос - нет, вы должны не закрывайте поток в этом случае. Контейнер должен это сделать, и если вы доберетесь до него, вы рискуете ввести тонкие ошибки в своем приложении.

59
ответ дан skaffman 21 August 2018 в 03:51
поделиться
  • 1
    Я согласен с этим ответом, вы также можете проверить ServletResponse.flushBuffer (): docs.oracle.com/javaee/1.4/api/javax/servlet/… – cyber-monk 7 March 2013 в 20:26
  • 2
    «если вы открыли поток, то вы должны закрыть его. Если вы этого не сделали, вы не должны " --- хорошо сказано – SrikanthLingala 17 May 2015 в 11:17
  • 3
    Это похоже на предложения, опубликованные на школьном совете », если вы откроете его, закройте его. Если вы включите его, выключите его. Если вы разблокируете его, заблокируйте его. [...] & Quot; – Ricardo 2 July 2015 в 21:32
  • 4
    Iv заметил, что я использую поток в начале своего кода и никогда больше не жду, что клиент ждет выполнения всего сервлета, но когда я вызываю close(), когда он выполняется с потоком, клиент возвращается немедленно, а остальная часть сервлета продолжает выполнение. Разве это не делает ответ немного более относительным? в отличие от окончательного да или нет – BiGGZ 15 January 2017 в 00:09
  • 5
    «если вы открыли поток, то вы должны закрыть его. Если вы этого не сделали, вы не должны. Убедитесь, что код симметричен. & Quot; - Итак, что, если вы создадите еще один поток, который обертывает этот поток? Трудно оставаться симметричным в этом случае, так как вызов внешнего внешнего потока обычно закрывает вложенный. – Steiny 23 March 2017 в 03:52

Если есть вероятность, что фильтр может быть вызван на «включенном» ресурсе, вы обязательно должны not закрыть поток. Это приведет к сбою включенного ресурса с исключением «stream closed».

4
ответ дан Skip Head 21 August 2018 в 03:51
поделиться
  • 1
    Спасибо, что добавил этот комментарий. Как ни странно, я все еще немного разбираюсь с проблемой - только сейчас я заметил, что в сервлет-шаблоне NetBeans включен код для закрытия выходного потока ... – Steven Huwig 19 October 2010 в 16:35

Другой аргумент против закрытия OutputStream. Посмотрите на этот сервлет. Это исключает. Исключение отображается в файле web.xml с ошибкой JSP:

package ser;

import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;

@WebServlet(name = "Erroneous", urlPatterns = {"/Erroneous"})
public class Erroneous extends HttpServlet {

  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    resp.setContentType("text/html;charset=UTF-8");
    PrintWriter out = resp.getWriter();
    try {
      throw new IOException("An error");
    } finally {
//      out.close();
    }
  }
}

Файл web.xml содержит:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <error-page>
        <exception-type>java.io.IOException</exception-type>
        <location>/error.jsp</location>
    </error-page>
</web-app>

И error.jsp:

<%@page contentType="text/html" pageEncoding="UTF-8" isErrorPage="true"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Error Page</title>
    </head>
    <body>
        <h1><%= exception.getMessage()%></h1>
    </body>
</html>

Когда вы загружаете /Erroneous в браузере, вы видите страницу с ошибкой, отображающую «Ошибка». Но если вы прокомментируете строку out.close() в указанном выше сервлете, повторно разверните приложение и перезагрузите /Erroneous, вы ничего не увидите в браузере. Я не знаю, что на самом деле происходит, но я предполагаю, что out.close() предотвращает обработку ошибок.

Протестировано с Tomcat 7.0.50, Java EE 6 с использованием Netbeans 7.4.

2
ответ дан user1872904 21 August 2018 в 03:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: