• 踩过的坑系列之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] 的元素。 
  • 相关阅读:
    深入理解系统调用
    基于mykernel 2.0编写一个操作系统内核
    如何评测一个软件工程师的计算机网络知识水平与网络编程技能水平?
    如何评测软件工程知识技能水平?
    深入理解TCP的三次握手及其源代码
    Socket与系统调用深度分析
    未来的图书会是什么样子?
    构建调试Linux内核网络代码的环境MenuOS系统
    Python笔记005-神奇的+=
    Python笔记004-元组的拆包和命名元组
  • 原文地址:https://www.cnblogs.com/lylife/p/11667228.html
Copyright © 2020-2023  润新知