0

我想从 a 读取前 x 个字节java.net.URLConnection(尽管我没有被迫使用此类 - 欢迎其他建议)。

我的代码如下所示:

val head = new Array[Byte](2000)  
new BufferedInputStream(connection.getInputStream).read(head)
IOUtils.toString(new ByteArrayInputStream(head), charset)

它可以工作,但这段代码是否只从网络加载前 2000 个字节?

下一次审判

正如'JB Nizet'所说,使用缓冲输入流没有用,所以我尝试了InputStreamReader

val head = new Array[Char](2000)  
new InputStreamReader(connection.getInputStream, charset).read(head)
new String(head)

此代码可能更好,但加载时间大致相同。那么这个过程会限制传输的字节吗?

4

2 回答 2

7

不,它没有。它最多可以读取 8192 字节(默认缓冲区大小BufferedInputStream)。它还可以读取 0 个字节,或 0 到 2000 之间的任意字节数,因为您不检查实际已读取的字节数,以及该read()方法返回的字节数。

最后,根据 charset 的值以及 HTTP 响应使用的实际 charset 的值,这可能会返回一个不正确的字符串,或者一个在多字节字符中间被截断的字符串。您应该使用阅读器来阅读文本。

我建议您阅读Java IO 教程

于 2013-01-22T12:36:32.230 回答
5

您可以read(Reader, char[])从 Apache Commons IO 使用。只需将 2000 个字符的缓冲区传递给它,它就会用尽可能多的字符填充它,最多 2000 个。

确保您理解其他答案/评论中的反对意见,特别是:

  • 不要使用Buffered...包装器,这违背了您的意图。
  • 如果您读取文本数据,则使用 aReader读取 2000个字符而不是InputStream读取 2000个字节。正确的过程是从响应 ( Content-Type) 的标头中确定字符编码并将该编码设置为InputStreamReader.
  • read(char[])在 a上调​​用plainReader不会完全填满你给它的数组。无论数组有多大,它都可以读取一个字符!
  • 之后不要忘记关闭阅读器。

除此之外,我强烈建议您使用Apache HttpClient来支持java.net.URLConnection. 它更加灵活。


编辑:要了解 和 之间的区别Reader.readIOUtils.read值得研究后者的来源:

public static int read(Reader input, char[] buffer,
                       int offset, int length)
    throws IOException
{
    if (length < 0) {
        throw new IllegalArgumentException("Length must not be negative: " + length);
    }
    int remaining = length;
    while (remaining > 0) {
        int location = length - remaining;
        int count = input.read(buffer, offset + location, remaining);
        if (EOF == count) { // EOF
            break;
        }
        remaining -= count;
    }
    return length - remaining;
}

由于Reader.read可以读取少于给定长度的字符(我们只知道它至少为 1 并且最多为长度),我们需要迭代调用它直到我们得到我们想要的数量。

于 2013-01-22T17:02:41.890 回答