由Java属性文件*.properties中getParameter(String key)出现乱码引发的探索

原文片段剪辑:

File f = Resources.getResourceAsFile(OpenAdDefine.CHANNELID_CONFIG);

Properties props = new Properties();

props.load(new FileInputStream(f));


//下面的test1与test2相关代码是自己遇到问题时的测试

String test1 = seq.getPosition();//seq是读取数据库(采用gbk方式连接读取数据库)时获得的一个对象,有属性为字符串内型的变量position


Iterator<Object> keySetIterator = props.keySet().iterator();

keySetIterator.next();
String test2 = keySetIterator.next().toString();


System.out.println("test1=" + test1 + ", test2=" + test2 + ", " + test1.equals(test2));
String test3 = new String(test1.getBytes(), "GBK");
String test4 = new String(test2.getBytes(), "GBK");
System.out.println("test3=" + test3 + ", test4=" + test4 + ", " + test3.equals(test4));

String test5 = new String(test1.getBytes("GBK"), "GBK");
String test6 = new String(test2.getBytes("GBK"), "GBK");
System.out.println("test5=" + test5 + ", test6=" + test6 + ", " + test5.equals(test6));

String test7 = new String(test1.getBytes("ISO-8859-1"), "GBK");
String test8 = new String(test2.getBytes("ISO-8859-1"), "GBK");
System.out.println("test7=" + test7 + ", test8=" + test8 + ", " + test7.equals(test8));

String test9 = new String(test1.getBytes("UTF-8"), "GBK");
String test10 = new String(test2.getBytes("UTF-8"), "GBK");
System.out.println("test9=" + test9 + ", test10=" + test10 + ", " + test9.equals(test10));

String test11 = new String(test1.getBytes("GBK"), "ISO-8859-1");
System.out.println("test11="+test11 + ", " + test11.equals(test2));

// 测试结束


channelId = props.getProperty(new String(seq.getPosition().getBytes(), "ISO-8859-1"));// 根据位置从配置文件中获取channelId
if (channelId == null)

 {
channelId = props.getProperty(new String(seq.getPosition()
.getBytes(), "utf-8"));
}
if (channelId == null)

{
channelId = props.getProperty(new String(seq.getPosition()
.getBytes(), "GBK"));

}
if (channelId == null)

{
throw new Exception("get channelid failed, channelid is "
+ channelId);

}


分析得出结果:

现在问题出现在,当channelidconfig.properties配置文件中key是中文时,那么seq.getPosition即字符串test1(编码为GBK),实例是:

test1="标清广告背景图片“(编码为GBK,因为从数据库中获取来的),而配置文件中的test2(即想用props.getProperty(key)的key)全都会是Java默认的字符编码的”ISO-8859-1",所以当我们用打印语句System.out.println(test1)打印的是中文“标清广告背景图片",而用打印语句System.out.println(test2)打印的却是乱码,而且打印System.out.println(test1.equals(test2))结果也显示为false。


解决问题的方法是这样的:

第一种方法:变test1, String test3 = new String(test1.getBytes("GBK"), "ISO-8859-1"),结果test3.equals(test2)为true ;

第二种方法:变test2, String test4 = new String(test2.getBytes("ISO-8859-1"), "GBK"), 结果test1.equals(test4)为true。

(“备注说明”:上面涉及到的”ISO-8859-1"其实都可以不用写,因为Java字符串默认的字符编码操作就是“ISO-8859-1")


联想探索:

上面一一连串的推测与结论表面上似乎都是对的,但是一个“备注说明”,理论上基于上面的实验与推论应该完全正确,然而结果不是我们想象的那样,经多方面分析,查看源代码,一想再想,还是源代码最能说明问题,其实java.lang.String中的构造方法new String(byte[] bytes)和getBytes()源代码里面都有这样的代码:

String csn = Converters.getDefaultEncodingName();
try {
   return decode(csn, ba, off, len);
} catch (UnsupportedEncodingException x) {
   Converters.resetDefaultEncodingName();
   warnUnsupportedCharset(csn);
}
try {
   return decode("ISO-8859-1", ba, off, len);
} catch (UnsupportedEncodingException x) {
   // If this code is hit during VM initialization, MessageUtils is
   // the only way we will be able to get any kind of error message.
   MessageUtils.err("ISO-8859-1 charset not available: "
    + x.toString());
   // If we can not find ISO-8859-1 (a required encoding) then things
   // are seriously wrong with the installation.
   System.exit(1);
   return null;
}

虽然现在Converters.getDefaultEncodingName()和类sun.io.Converters本身都已被废弃(查证可以用Charset.defaultCharset().name()代替,更多功能由java.nio.charset.CharSet类代替),但是源代码里毕竟有这样的代码,所以再采用“ISO-8859-1”编码字节数组组成字符串,或者字符串得到字节数组时都会先采用系统默认的字符集编码,经实践证明,我的Windows操作系统由Charset.defaultCharset().name()或者Converters.getDefaultEncodingName()得到的都是GBK,而Linux系统得到的是UTF-8,所以这个String的构造方法new String(byte[] bytes)和getBytes()方法是不能乱用的,依赖系统属性的!正如此,解决问题的方法还是上面所说的两种,而且不能省略“ISO-8859-1”,即不能偷懒用备注中说明的方法解决问题,既然这样不仅限于另一个疑惑,那么java.util.Properties中的Key为什么都是ISO-8859-1编码的字符串呢,再看源代码,发现他底层采用构造字符串的方法是new String(char value[], int offset, int count)并未涉及到字节数组那样转换为字符串的操作,默认字符char编码就是ISO-8859-1吧(这里现在我也不敢断定了)。


回顾总结:

此问题出于Java读取Properties配置文件产生乱码源头,引发对字符串编码的一阵阵研究,对于自己字符串编码方面帮助受益颇多,记下来作为知识的积累!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值