如何使用Java / Scala从URL加载前x个字节?

时间:2013-01-22 12:23:53

标签: java scala url urlconnection

我想从java.net.URLConnection读取前x个字节(虽然我不是被迫使用这个类 - 欢迎其他建议)。

我的代码如下所示:

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)

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

2 个答案:

答案 0 :(得分:7)

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

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

我建议你阅读Java IO tutorial

答案 1 :(得分:5)

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

请务必了解其他答案/评论中的异议,特别是:

  • 不要使用Buffered...包装,这违背了你的意图。
  • 如果您阅读文本数据,请使用Reader读取2000 字符而不是InputStream读取2000 字节。正确的程序是从响应的标头(Content-Type)确定字符编码,并将该编码设置为InputStreamReader
  • read(char[])上调用普通Reader将无法完全填充您提供给它的数组。无论数组多大,它都只能读取一个字符!
  • 不要忘记之后关闭读者。

除此之外,我强烈建议您使用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,最多只有长度),我们需要迭代调用它直到得到我们想要的数量。