中文乱码就是编码解码的问题,编码简介-编码方式
先说关键点:字节和字符间的编码解码,一定要表明编码方式。
举例开发中遇到的问题:
1.利用officeonline实现在线播放ppt, ppt文件名是中文, 将文件名用DEC加密后传入接口,接口对其解密。
在ide中,解密后是正确的中文名称,但打包运行或上环境,文件名称就乱码了。
在网上搜,有种在DES加密解密中 加入base64加密解密的解决办法,确实可以防止中文乱码问题,但因为业务需求,文件名称加密后的内容必须只含有数字和字母,不能有特殊符号,这种base64会有特殊符号,也不能使用。
最后发现,在DES解密时,是先得到字节数组,在用字符串构造方法得到字符串,这个步骤少了编码方式。
正确方式:
可以看到,在字符串data 编码为字节时要指定编码方式UTF-8,如果这少了,也会乱码。在用字节数组构造字符串时,也需要指定编码方式。
public static String decrypt(String data, String cryptKey) throws Exception {
return new String(decrypt(hex2byte(data.getBytes("UTF-8")),cryptKey.getBytes())
,"UTF-8");
}
//DES解密
private static byte[] decrypt(byte[] data, byte[] key) throws Exception {
// DES算法要求有一个可信任的随机数源
SecureRandom sr = new SecureRandom();
// 从原始密匙数据创建一个DESKeySpec对象
DESKeySpec dks = new DESKeySpec(key);
// 创建一个密匙工厂,然后用它把DESKeySpec对象转换成
// 一个SecretKey对象
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
SecretKey securekey = keyFactory.generateSecret(dks);
// Cipher对象实际完成解密操作
Cipher cipher = Cipher.getInstance(ALGORITHM);
// 用密匙初始化Cipher对象
cipher.init(Cipher.DECRYPT_MODE, securekey, sr);
// 现在,获取数据并解密
// 正式执行解密操作
return cipher.doFinal(data);
}
错误方式:
public static String decrypt(String data, String cryptKey) throws Exception {
return new String(decrypt(hex2byte(data.getBytes("UTF-8")), cryptKey.getBytes()));
}
2.用JAVA URL类获取阿里云oss中文文件乱码
在oss中上传了一些中文名称的文件,oss给出的path路径 比如: http://domain/bucket/152/IOT物联平台123_幻灯片1.JPG,
在oss打开公有功能时,在浏览器上输入url可以直接下载成功,但是用URL类访问失败。
这是因为浏览器帮我们做了编码:
登录oss查看文件真正的path时,发现url是编码后的,所以必须转码后再用URL类访问才能成功。
URL url = new URL(fileName);
uc = (HttpURLConnection) url.openConnection();
is = uc.getInputStream();
if (uc.getResponseCode() != 200) {
logger.info("连接文件url失败,返回状态码 -> {}, 响应信息 -> {}", uc.getResponseCode(), uc.getResponseMessage());
logger.info("连接文件url失败,打开文件预览异常,打开的文件地址为{}", fileName);
info.setErrorMsg("打开文件预览异常!");
}
对url进行编码,空格也需要编码,否则失败。
public static String encodeUrl(String url) {
String path = url.substring(0,url.lastIndexOf("/")+1);
String query = url.substring(url.lastIndexOf("/")+1);
try {
String encodeQuery = URLEncoder.encode(query, "UTF-8");
return path + encodeQuery;
} catch (UnsupportedEncodingException e) {
return "Issue while encoding" + e.getMessage();
}
}