Java Spring boot Socket 字节数组接收中文字符串 截断bug

  • 场景描述:
    在spring boot中使用sokect 接受来自PHP服务器的执行结果。发送请求后得到的内容中含有乱码,确认了所有编码格式均为UTF-8,并且php端调用的接口所使用的方法执行后返回的是正常的结果。因此怀疑是否是因为Spring boot Socket问题导致,再搜索文章并且调试之后,发现并非此原因。 网上推荐使用BufferReader读取 但是内置方法不包含按byte[]读取,因此放弃。 还有一种解释是说UTF-8中文为3个字节,符号数字为单字节,如果以1024长度的字节数组截取有可能第1023为中文的半个字符,而下一个字符到了下一组中。而此时因为已经使用toString获取了字符串,就导致了最后一个字符为乱码。

  • 解决方案:
    使用ByteBuffer先预存所有的byte[],在读取完所有数据之后,再进行String的转换。

  • 代码:

        String reqStr="请求内容";
        ByteBuffer buf = ByteBuffer.allocate(4 + reqStr.getBytes().length);
        buf.putInt(reqStr.getBytes().length);
        buf.put(reqStr.getBytes());
        //socket连接设置   1.7语法糖
        Socket socket=new Socket(jobTagSocketHost,config.getApiSocketPort());)
        {
        //调用内部socket接口
        socket.getOutputStream().write(buf.array());//发送请求字符串
        //读取数据长度
        byte[] size = new byte[4];
        socket.getInputStream().read(size);
        int size_t = Bytes.toInt(size, 0, 4);
        //读取数据,每次读取1024字节,防止数据丢失,或读不全
        byte[] data = new byte[1024];
        //如果不使用bytebuffer 会导致循环时转换的最后一个字节有可能是中文的半个字节
        ByteBuffer bb= ByteBuffer.allocate(size_t);
        while (size_t > 0) {
            int dataSize = socket.getInputStream().read(data);
            bb.put(Arrays.copyOfRange(data, 0, dataSize));
            size_t -= dataSize;
        }
        //最终-查询结果字符串
        String finalStr = new String(bb.array());
  • 问题:
    有可能会有大量数据情况 会导致OOM发生,预申请的空间可能过大,需要在申请前进行判断,如果超过某个大小则抛出异常。比如 size为2048000000 ,2G 则必然会在小jvm设置下发生 java heap out of memory 问题。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值