解决java socket在传输汉字时出现截断导致乱码的问题
解决java socket在传输汉字时出现截断导致乱码的问题
当使用socket进行TCP数据传输时,传输的字符串会编码成字节数组,当采用utf8编码时,数字与字母长度为1个字节,而汉字一般为3个字节。这里参考
字符集之在UTF-8中,一个汉字为什么需要三个字节? - 苦涩的茶 - 博客园 (cnblogs.com)
如果传输的字符串是数字,字符和汉字混杂。在数据的接收端,每次调用read方法接收的byte数组的长度是一定的,由于数字,字母和汉字对应的utf8编码长度不同,可能会导致末尾的汉字被截断。举个例子:假定接收端每次调用read方法读取的byte数组长度为20。而发送短发送的字符串为"Hello World! 你好中国!",转换为byte数组为
[0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x20, 0xE4, 0xBD, 0xA0, 0xE5, 0xA5, 0xBD, 0xE4, 0xB8, 0xAD, 0xE5, 0x9B, 0xBD, 0x21]
在接收端第一次读取的byte数组长度为20,对应的byte数组为
[0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x20, 0xE4, 0xBD, 0xA0,0xE5, 0xA5, 0xBD, 0xE4]
转换为字符变成了"Hello World! 你好�",最后一个字符出现了乱码。这是因为前19个字节(英文空格加标点共13个字节,前两个汉字占六个字节)转换成了字符串"Hello World! 你好",最后一个字节对应着字符"中"的三个字节[0xE4, 0xB8, 0xAD]中的第一个字节0xE4。但是这个一个字节(首位为1没有对应的单字节字符)是无法转换为可见的字符的。这里就是出现了隔断。"中"的剩余两个字节为下一个read读取得到的字节数组的前两两个字节。
为了能够解决截断问题,我们需要判断接收到的字节数组的最后两个字节是否为被截断的汉字字符的对应的字节。
为了解决这个问题,首先了解一个汉字字符在UTF-8编码中的格式。基本上常见的汉字字符在UTF-8编码中都是三个字节。在UTF-8编码方案中,对三字节编码的每个字节都做了规定:
如果是三个字节编码的话,那么第一个字节的前三位为111,第四位为0,剩余的两个字节的前两位都为10
比如汉字"中",对应的三个字节用二进制可以表示为:[1110 0100, 1011 1000, 1010 1101]
满足UTF-8编码的要求。
如何根据编码格式来判断得到的byte数组的最后一个或者两个字节是被截断的呢。
我们将byte数组的最后两个字节定义为firstByte和secondByte,分别对应着导数第二个字节和倒数第一个字节。
情况1:
如果倒数第一个字节符合1110 xxxx格式,说明这个字节对应着汉字字符的第一个字节,剩余的两个字节在下个被接收的byte数组中,发生了截断。我们需要暂存最后一个字节secondByte,与下面一个byte数组的前两个字节组合在一起解析出汉字。
情况2:
如果倒数第二个字节的二进制符合1110 xxxx格式,那就说明这个字节对应着汉字字符的第一个字节,最后一个字节对应汉字字符的第二个字节,第三个字节为下个被接收的byte数组第一个字节,发生了截断。这种情况需要将byte数组的最后两个字符保存起来,与下面一个byte数组的第一个字节结合起来才能解析出对应的汉字。
对于如何判断一个字节是否符合1110 xxxx格式,这里我们采用掩码的方式,保留firstByte的前四位,屏蔽后四位(将后四位置零)。
判断 firstByte & 11100000 == 11100000是否成立,如果成立对应第一种情况,否则
判断secondByte & 11100000 == 11100000是否成立,成立则对应第二种情况
解决java socket在传输汉字时出现截断导致乱码的问题的更多相关文章
- java socket通信-传输文件图片--传输图片
ClientTcpSend.java client发送类 package com.yjf.test; import java.io.DataOutputStream; import java.io ...
- 解决java web中safari浏览器下载后文件中文乱码问题
解决java web中safari浏览器下载后文件中文乱码问题 String fileName = "测试文件.doc"; String userAgent = request.g ...
- java socket 网络通信 指定端口的监听 多线程 乱码
Java Socket编程 对于Java Socket编程而言,有两个概念,一个是ServerSocket,一个是Socket.服务端和客户端之间通过Socket建立连接,之后它们就可以进行通信了.首 ...
- java socket之传输实体类对象
一.TCP编程 TCP协议是面向连接的.可靠地.有序的,以字节流的方式发送数据.java实现TCP通信依靠2个类:客户端的Socket类和服务器端的ServerSocket类. 基于TCP通信 ...
- Java socket字节流传输的示例
服务端server端: package com.yuan.socket; import java.io.*; import java.net.ServerSocket; import java.net ...
- 解决 java循环中使用 Map时 在put值时value值被覆盖的问题
其实很简单,只需要把容器换成list 然后在循环中,每次循环末尾map = new HashMap() 或者直接在循环中一开始就实例化hashmap(Map map = new HashMap();) ...
- 解决java中ZipFile解压缩时候的中文路径和乱码问题
JAVA中对jar文件或zip文件解压的时候,能够使用JDK内置的API:JarFile和ZipFile,在windows下解压这2种格式文件的时候,常常报下面错误: Exception in thr ...
- socket 发送字符串0x00时被截断
发送数据如下: aa 02 02 00 00 00 6f 6b 02 00 00 00 55 数据是以字符数组的形式(char msg[])存储发送的,send时发送长度填写的strlen(msg), ...
- ASP.NET开发在JavaScript有中文汉字时出现乱码时简单有效的解决
一般情况在使用ASP.NET开发使用JavaScript有中文汉字时不会出现乱码情况,比如:alert('您看到我了吗?');这样直接输入中文汉字的代码中是不会出现乱码的,如果出现了,一是检查Web. ...
随机推荐
- C++基于armadillo im2col的实现
最近学习CNN,需要用到im2col这个函数,无奈网上没有多少使用armadillo的例子,而且armadillo库中似乎也没有这个函数,因此自己写了. im2col的原理网上一大把,我懒得写了. 1 ...
- .NetCore·集成Ocelot组件之完全解决方案
阅文时长 | 11.04分钟 字数统计 | 17672.8字符 主要内容 | 1.前言.环境说明.预备知识 2.Ocelot基本使用 3.Ocelot功能挖掘 4.Ocelot集成其他组件 5.避坑指 ...
- 排坑·ASCII码为160的空格(nbsp)
阅文时长 | 2.83分钟 字数统计 | 1345.2字符 『排坑·ASCII码为160的空格(nbsp)』 编写人 | SCscHero 编写时间 | Wednesday, September 9, ...
- istio部署问题Q&A
端口绑定无权限 创建Gateway,提示绑定端口无权限. 2020-12-27T12:25:30.974288Z warning envoy config gRPC config for type.g ...
- 使用 yum-cron 自动更新 Linux系统
使用 yum-cron 自动更新 Linux系统 Linux系统技术交流QQ群(1675603)验证问题答案:刘遄 我知道如何使用 yum 命令行 更新系统,但是我想用 cron 任务自动更新软件 ...
- 10.6 ip:网络配置工具
ip命令是iproute软件包中的一个强大的网络配置工具,用于显示或管理Linux系统的路由.网络设备.策略路由和隧道. ip [option] [object] [command] ip [选项 ...
- STM32自己的封装库
以前一直使用STM32的标准库,需要一步步地将代码加进去,将编译选项设置好,然后再编译整个工程. 这个编译过程是一个相当慢的过程!完全编译大约需要一支烟的时间.每次建立工程都这么编译,是一个相当浪费时 ...
- Go语言之main包
Go语言的代码通过包(package)组织,包类似于其他语言里的库(libraries)或者模块(modules).一个包由位于单个目录下的一个或多个go源文件组成,目录定义包的作用.每个源文件都以一 ...
- skynet debug console 使用
预读 关于如何使用 skynet 可以参考 wiki 文档 更多实战内容见 https://www.lanqiao.cn/courses/2770 优惠码:2CZ2UA5u 环境测试搭建 使用示例代码 ...
- typora的一些使用
1.介绍typora 支持markdown语法的一款写作app 真的足够简洁高效 2. typora和其他工具配合实现功能 如插入图片 截图 gif等等图库 smms图库的使用 需要使用PicGo和s ...