踩过的坑系列之InputStream.read(byte[])方法

  项目之前都是好好的,最近现场那边出现一个问题,报错不是合法的json字符串,这个json字符串是通过http请求访问获得的。

  通过直接在浏览器上直接访问http这个请求,发现返回的json也是完全正确的。后来排查代码才发现了原来错误出在从字节流中读取数据这里:

  看下之前出错代码:这个方法是处理InputStream,然后返回成一个字符串。

 1 public String process(InputStream in, String charset) {
 2      byte[] buf = new byte[1024];
 3      StringBuffer sb = new StringBuffer();
 4      try {
 5          while (in.read(buf) != -1) {
 6              sb.append(new String(buf, charset));
 7          }
 8     } catch (IOException e) {
 9          e.printStackTrace();
10     }
11      return sb.toString();
12 }

   有问题的代码在第6行,发现之前项目没出错的原因是InputStream里面的数据少,还不够1024个字节,while那里循环一次就好了,得到一个正确格式的json串;后面出错了是因为InputStream里面数据比较多,while需要2次了,第一次读取之后buf里面满了,第二次读取发现read(byte[])方法不会去清空缓冲区数组,第二次实际上read字节只有100个,buf里面只替换前100个字节内容,然后通过第6行代码append到字符串里了,就造成了最后获得的字符串不是json格式,造成之后json解析出错。

  知道问题后,将之前代码改为下,既然每次不会去清空缓冲区数组内容,那就通过读取长度来append字符串,问题解决:

 1 public String process(InputStream in, String charset) {
 2     byte[] buf = new byte[1024];
 3     StringBuffer sb = new StringBuffer();
 4     int len = 0;
 5     try {
 6         while ((len=in.read(buf)) != -1) {
 7             sb.append(new String(buf, 0, len, charset));
 8         }
 9     } catch (IOException e) {
10         e.printStackTrace();
11     }
12     return sb.toString();
13 }

 

    后来查了下JDK API,发现API上也说明过了,只是以前没注意,关键在于加黑字体,不影响b[k]到b[b.length-1]的元素:

  附上API:

    public int read(byte[] b) throws IOException    
  从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。以整数形式返回实际读取的字节数。
  在输入数据可用、检测到文件末尾或者抛出异常前,此方法一直阻塞。
  如果 b 的长度为 0,则不读取任何字节并返回 0;否则,尝试读取至少一个字节。如果因为流位于文件末尾而没有可用的字节,则返回值 -1;否则,至少读取一个字节并将其存储在 b 中。将读取的第一个字节存储在元素 b[0] 中,下一个存储在 b[1] 中,依次类推。读取的字节数最多等于 b 的长度。设 k 为实际读取的字节数;这些字节将存储在 b[0]b[k-1] 的元素中,不影响 b[k]b[b.length-1] 的元素。 

 

posted on 2022-03-28 18:15  程序人生ly  阅读(680)  评论(0编辑  收藏  举报