开发java chaincode过程中遇到一个中文乱码的问题。都是官方的demo,请求的sdk是用java写的,部署的chaincode有两种选择(不考虑node),一种go语言写的chaincode,一种java写的。
笔者实际调用发现,相同的客户端如果请求go的chaincode,中文是能够正确处理的。如果请求java的客户端就会产生乱码,一个中文产生一个问号 这样。
分析:
通过 java中的 System.setProperty("file.encoding","UTF-8"); 获取编码,结果是 US_ACSII。 说明javaenv 容器默认的编码方式。搜索发现大多在应用读取文件时会出现这个问题,文件的编码为ASCII。
怀疑参数接收过程中是从文件读取。
方案:
尝试修改应用编码字符集。因为启动的过程是fabric自己处理的,减少对原有内容修改的原则,尽量在工程中修改字符集。
每个chaincode 都默认会有一个main方法启动。我觉得这个过程类似springboot的application中的main方法。在这个main中start之前添加代码:
System.setProperty("file.encoding","UTF-8");
发现不生效。原因是因为java中的字符集defaultCharset 默认初始化一次,设置UTF-8的之前这个值已经生效了,所以这里怎么设置都只会去取之前设置的字符集。
这里采用一种方案,利用java的反射机制,获取类Charset的 defaultCharset,将其设置为null。这样就相当于欺骗jvm,这个值是空的,让它去取我们之前设置的UTF-8。
System.setProperty("file.encoding","UTF-8");
try {
Field charset = Charset.class.getDeclaredField("defaultCharset"); charset.setAccessible(true); charset.set(null,null); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); }
这种方案能够生效,但我个人认为这是一种极端的方案,fabric理应处理好或者提供修改字符集的地方。