5

我目前使用以下函数来做一个简单的 HTTP GET。

public static String download(String url) throws java.io.IOException {
    java.io.InputStream s = null;
    java.io.InputStreamReader r = null;
    //java.io.BufferedReader b = null;
    StringBuilder content = new StringBuilder();
    try {
        s = (java.io.InputStream)new URL(url).getContent();

        r = new java.io.InputStreamReader(s);
        //b = new java.io.BufferedReader(r);

        char[] buffer = new char[4*1024];
        int n = 0;
        while (n >= 0) {
            n = r.read(buffer, 0, buffer.length);
            if (n > 0) {
                content.append(buffer, 0, n);
            }
        }
    }
    finally {
        //if (b != null) b.close();
        if (r != null) r.close();
        if (s != null) s.close();
    }
    return content.toString();
}

我认为没有理由使用,BufferedReader因为我只是要按顺序下载所有内容。我认为BufferedReader在这种情况下没有用是正确的吗?

4

4 回答 4

5

在这种情况下,我会像你一样做(使用字节数组进行缓冲,而不是使用流缓冲区之一)。

不过也有例外。您看到缓冲区(这次是输出)的一个地方是在 servlet API 中。在调用flush()之前,数据不会写入底层流,允许您缓冲输出,但如果发生错误则转储缓冲区并改为写入错误页面。如果您需要使用mark(int)reset()重置流以重新读取,则可以缓冲输入。例如,您可能会在决定将流传递给哪个内容处理程序之前检查文件头。

不相关,但我认为你应该重写你的流处理。此模式最适合避免资源泄漏:

    InputStream stream = new FileInputStream("in");
    try { //no operations between open stream and try block
        //work
    } finally { //do nothing but close this one stream in the finally
        stream.close();
    }

如果您要打开多个流,请嵌套 try/finally 块。

您的代码正在做的另一件事是假设返回的内容是用 VM 的默认字符集编码的(尽管这可能就足够了,具体取决于用例)。

于 2008-08-28T15:03:31.053 回答
1

没错,如果您使用 BufferedReader 来读取 HTTP 内容和标头,您将需要 InputStreamReader,这样您就可以逐字节读取。

在这种情况下,BufferedReader 有时会做一些奇怪的事情……尤其是在读取 HTTP POST 标头时,有时您将无法读取 POST 数据,如果您使用 InputStreamReader,您可以读取内容长度并读取那么多字节。 .

于 2008-08-28T00:16:40.937 回答
1

每次调用InputStreamReader的 read() 方法之一都可能导致从底层字节输入流中读取一个或多个字节。为了实现字节到字符的有效转换,可以从底层流中预先读取比满足当前读取操作所需的更多的字节。

于 2010-01-18T17:11:41.060 回答
0

我的直觉告诉我,由于您已经使用字节数组执行缓冲,因此使用 BufferedReader 是多余的。

于 2008-08-28T00:18:03.023 回答