Netty的深入浅出--33.java字符集编码解码详解

对于字符集编码来说,很多人都不太理解,一直是一个老大难问题。

下面这个例子采用的是NIO流形式读取文件,不是IO流哦

下面先写一个例子,将一个文件拷贝到另外一个文件中:

目的是将NioTest13_In.txt文件内容拷贝到NioTest13_Out.txt中

获取文件权限:

 获取channel

将input文件映射到ByteBuffer中

接下来就是encode和decode,编码和解码,

encode编码就是将字符串编码成字节数组;

decode解码就是将字节数组解码成字符串。

设置字符集编码类型:

获取到encode对象, decode对象

将内存映射的bytebuffer解码成一个charBuffer

将charBuffer编码成一个byteBuffer

 写入到output文件中

 运行程序

 

现在将字节码类型改成iso

运行程序:

纳尼!结果没有出现乱码!而且输出文件编码格式还是utf-8,这是神马情况,是不是颠覆三观了╮(╯▽╰)╭

为什么中文在iso-8859-1的情况下还能正常输出

大部分情况下iso编码类型情况下的中文都会出现乱码,而现在却是没有出现;

现在就出现一个矛盾,源文件是utf-8的编码格式,而解码器和编码器都是iso-8859-1,生成的文件竟然还是utf-8,暂时不要急着找答案,继续往下面看:

查看所有可用字符集:

 我们先了解一下所有比较常用的字节码类型之间的关系

首先最早出现的ASCII码:

1个ASCII码可以表示128个字符,因此对于西方国家来说已经完全够了 

从美国和英国之后计算机传入到德国法国,发现ASCII码无法全部表达,所以就出现了iso-8895-1;

因为iso-8895-1是ASCII的一个扩展,它完全兼容ASCII码。

但是问题又出现了,256个字符表示德国法国的字符是够的,而我们中国和朝鲜等国家的字符却远远不够

因此出现了由我们中国制定的gb2312

 但是问题又来了,在指定gb2312的时候,没有考虑到很多生僻字,因此出现了gbk,不过后来又发现gbk对于少数汉字还是不能表示,接着有出现了gb18030;

这时候台湾自己也指定了一套编码规则:big5(因为他们是繁体中文,我们大陆是简单中文,写法不一样)

但是大问题来了,如果每个国家都指定一套自己的编码格式,那操作系统不就乱套了吗。这时候就出现了国际标准化组织,它将全球所以的语言全部集中起来,制定了unicod

但是问题又来了,unicode需要两个字节来表示一个字符,这样的话,对于英语使用的国家来说,表示一个字符只需要7bit(8bit等于1个字节),现在文件的存储量翻了两倍,对于存储量大的来说这翻的倍数是非常可怕的。

 最后utf出现了

 

现在我们 的问题又回到之前:

对于iso-8895-1存储数据的时候,按照8bit(一个字节)来存储一个字符

在utf-8中英文都是用一个字节来存储的,汉字是三个字节:

现在“你好”这两个汉字解码之后成为6个字节,这个时候肯定是乱码的。

如果是12的话,实际上获取的是第一个汉字“你”的第一个字节

所以说运行之后就产生了一个乱码:

我假设的是“你好”的ASCII码是下面六个字节,可以直观的打印出来 

所以现在,你应该就能理解了,当如果你的汉字个数不是偶数的话,你通过iso编码和解码之后肯定乱码,至于为什么自己多想想咯^_^ 

2023-07-14 15:19:01.215 WARN 7308 --- [sson-netty-2-15] io.netty.util.concurrent.DefaultPromise : An exception was thrown by org.redisson.misc.RedissonPromise$$Lambda$888/0x00000008008f7440.operationComplete() java.lang.NullPointerException: null 2023-07-14 15:19:01.216 ERROR 7308 --- [sson-netty-2-15] o.r.c.SentinelConnectionManager : Can't execute SENTINEL commands on /172.24.107.11:26379 org.redisson.client.RedisException: ERR No such master with that name. channel: [id: 0x2d66827d, L:/172.23.9.103:46812 - R:/172.24.107.11:26379] command: (SENTINEL SLAVES), params: [mymaster] at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:365) ~[redisson-3.13.3.jar:3.13.3] at org.redisson.client.handler.CommandDecoder.decodeCommand(CommandDecoder.java:196) ~[redisson-3.13.3.jar:3.13.3] at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:134) ~[redisson-3.13.3.jar:3.13.3] at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:104) ~[redisson-3.13.3.jar:3.13.3] at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:501) ~[netty-codec-4.1.51.Final.jar:4.1.51.Final] at io.netty.handler.codec.ReplayingDecoder.callDecode(ReplayingDecoder.java:366) ~[netty-codec-4.1.51.Final.jar:4.1.51.Final] at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276) ~[netty-codec-4.1.51.Final.jar:4.1.51.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.51.Final.jar:4.1.51.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.51.Final.jar:4.1.51.Final] at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.51.Final.jar:4.1.51.Final] at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.51.Final.jar:4.1.51.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.51.Final.jar:4.1.51.Final] at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.51.Final.jar:4.1.51.Final] at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.51.Final.jar:4.1.51.Final] at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) ~[netty-transport-4.1.51.Final.jar:4.1.51.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:714) ~[netty-transport-4.1.51.Final.jar:4.1.51.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:650) ~[netty-transport-4.1.51.Final.jar:4.1.51.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:576) ~[netty-transport-4.1.51.Final.jar:4.1.51.Final] at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) ~[netty-transport-4.1.51.Final.jar:4.1.51.Final] at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) ~[netty-common-4.1.51.Final.jar:4.1.51.Final] at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.51.Final.jar:4.1.51.Final] at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.51.Final.jar:4.1.51.Final] at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na] 解决方法
07-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值