You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:06:27