Java 为什么将输入读取为流比读取字符串更节省内存?

Java 为什么将输入读取为流比读取字符串更节省内存?,java,stream,httpclient,Java,Stream,Httpclient,我们正在使用HTTPClient实现RESTAPI 我们正在使用以下命令读取服务器响应: method = new PostMethod(url); HttpClient client = new HttpClient(); int statusCode = client.executeMethod(method); String responseBody = method.getResponseBodyAsString(); 当我们这样做时,我们会得到以下警告: Dec 9, 2009 7:

我们正在使用HTTPClient实现RESTAPI

我们正在使用以下命令读取服务器响应:

method = new PostMethod(url);
HttpClient client = new HttpClient();
int statusCode = client.executeMethod(method);
String responseBody = method.getResponseBodyAsString();
当我们这样做时,我们会得到以下警告:

Dec 9, 2009 7:41:11 PM org.apache.commons.httpclient.HttpMethodBase getResponseBody
WARNING: Going to buffer response body of large or unknown size. Using getResponseBodyAsStream instead is recommended.
他们接着说:

HttpClient能够高效地 请求/响应正文流。大的 可以提交或接收实体 没有在内存中缓冲。这 如果有多个 可以执行HTTP方法 同时虽然有 方便的处理方法 字符串或字节等实体 不鼓励使用数组。 除非小心使用,否则它们很容易损坏 导致内存不足的情况, 因为它们意味着缓冲 内存中的完整实体


因此,我的问题是,如果您确实需要完整的响应作为字符串(即:存储在DB中,或使用DOM进行解析),为什么使用流会更节省内存?

整个过程并没有更节省内存。如果您从一个流中读取数据并将其放入字符串中,那么您只是将流程分成两部分,以便HttpClient类不会注意到它


如果确实需要整个字符串,则可以忽略警告。然后由您来确保每个请求不会占用太多内存,这样服务器就不会轻易被拒绝服务攻击打倒。

您的问题混淆了这一点

如果您确实需要整个响应作为字符串,那么就这样做

但是,如果你能侥幸逃脱,那就使用流

当您将整个响应加载到字符串中时,整个响应主体一次出现在内存中

使用流,每次只有一小部分响应保存在内存中


文档中说,尤其是同时处理多个大型请求时,将整个请求体加载到字符串中需要大量内存。

使用流比将整个实体作为字符串使用更有效,因为后者意味着

  • 在返回到代码之前,需要读取响应的全部内容,并且
  • 在服务器发送整个响应之前,无法将控件返回到代码
  • 如果您将响应作为流进行处理,那么您实际要做的是一次处理N个字节。这意味着您可以在远程服务器仍在发回下一段数据时开始处理第一个响应段。因此,如果您的用例允许您在接收数据时处理数据,那么这作为一种访问方法就更有意义

    但是,如果出于任何原因需要将整个响应作为一个字符串,那么流方法的所有效率对您都没有任何影响——因为即使您以片段形式读取响应,您仍然需要等待整个响应——并将其全部包含在单个字符串中——然后才能处理它


    只有当您有一个用例,可以在拥有整个响应主体之前开始处理响应时,您才可以使用流的效率。

    如果您要解析到
    org.w3c.Document
    (或者更好的是,
    org.jdom.Document
    ),直接使用流确实很容易。例:

    org.apache.http.HttpResponse hr = httpClient.execute(httpRequest);
    org.apache.http.HttpEntity he = hr.getEntity();
    org.jdom.input.SAXBuilder builder = new SAXBuilder();
    org.jdom.Document document = builder.build(he.getContent());