Android中BufferedReader读取char[]时触发StringIndexOutOfBoundsException
解决Socket读取JSON时的StringIndexOutOfBoundsException问题
这个问题我之前排查过类似的,其实根源很清晰——你没处理BufferedReader.read()返回-1的情况!
异常原因解析
从异常信息regionLength=-1就能看出来,你的messageLength变量拿到了-1,这是read()方法的标准返回值:当输入流已经到达末尾(也就是Socket连接被关闭,可能是服务器主动断开、网络中断或者连接超时),read会返回-1。这时候你直接把-1传给new String(buffer, 0, messageLength),自然会触发越界异常,因为构造String时的长度参数不能为负数。
至于之前正常运行数周突然出现,大概率不是你的代码问题,而是外部环境变化:
- 服务器端可能调整了连接超时策略,空闲连接被主动断开
- 近期网络环境波动,导致连接频繁中断
- 客户端和服务器之间的防火墙/代理新增了连接限制
修复方案
最直接的修复就是在构造字符串前先判断返回值,处理流结束的情况:
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); char[] buffer = new char[READ_BUFFER]; int messageLength = reader.read(buffer, 0, READ_BUFFER); // 核心:先判断流是否已结束 if (messageLength == -1) { // 这里处理连接断开的逻辑:比如关闭socket、触发重连、通知上层业务 try { socket.close(); } catch (IOException e) { e.printStackTrace(); } // 可以直接return终止当前监听,或者抛出自定义异常 return; } // 确认有效长度后再构造字符串 String message = new String(buffer, 0, messageLength);
额外稳定性优化建议
- 处理不完整的JSON消息:Socket是流式传输,一次read可能只拿到JSON的一部分,或者一次拿到多条消息。建议和服务器约定消息边界(比如用换行符分隔每条JSON,或者先传输消息长度再传内容),在客户端做消息拼接,确保拿到完整的JSON再解析。
- 增加异常捕获与重试:在
listenForMessages方法外层捕获IOException,处理连接中断、读取失败等情况,自动触发重连逻辑,提升应用的鲁棒性。 - 添加心跳机制:如果服务器会断开空闲连接,客户端可以定期发送心跳包(比如每隔30秒发一个小的JSON消息),维持连接活跃。
内容的提问来源于stack exchange,提问作者nicetrybro
相关产品推荐
相关产品推荐

