介绍
介绍
福哥的项目里面需要对字符串编码进行转换,从网上一搜,清一色的都是一样的教程,关键这些教程的方法还都不好使。
经过一番亲身测试,终于找到了解决可用的解决方法。
系统编码
在转换编码之前我们需要知道“系统编码”是什么,很多人会下意识地认为程序文件的编码就是“系统编码”,这是一个很大的误区。
其实“系统编码”是编译程序时候使用的编码,在不同情况下是不一样的。直接通过javac编译程序的话就是Windows的系统编码,一般情况下都是GBK编码;而使用IDEA之类的工具编译程序的话通常都是UTF-8编码。
如果程序文件的编码和编译程序的编码不一样,有可能会造成编译错误。
编译编码
无论是javac编译还是工具编译,都可以通过-encoding参数指定一个编译编码,语法如下。
javac -encoding utf-8 test.java
编码转换
程序编译后,代码里的常量会变转成Unicode码,使用Unicode码可以转成任何其他编码。为了保证程序不会因为编码异常崩溃,所有输入和输出的地方都会根据需要将Unicode编码转换成适合自己的编码。
String
字符串会在赋值的时候尝试将目标值转换成“系统编码”,如果失败就会出现“乱码”了。那么如果想在字符串里面存储非“系统编码”的数据呢?答案是肯定的,不能!!!
byte[]
字节数组在赋值的时候会原原本本地保存目标值的数据,它类似C++里面的char*。所以,大家可以发现大多数和外部媒介交互时候或者是进行编码转换的时候都需要先转为byte数组再进行处理。
转换
所谓的编码转换其实就是使用getBytes方法将Unicode码转换成指定编码的byte数组,然后在使用的地方直接传入这个byte数组。
什么?使用的地方不支持传入byte数组?对不起,那就是它不支持传入非“系统编码”数据了。
编码转换对象
给出一个编码转换对象的代码示例。其实这个对象使用价值不高,因为需要使用非“系统编码”的时候只需要调用getBytes就可以了。
public class TFEncoding { public static byte[] toBytes(String org, String toCharset){ try{ byte[] bytes = org.getBytes(toCharset); return bytes; } catch (UnsupportedEncodingException e){ } return null; } public static String toString(byte[] bytes, String toCharset){ try{ String out = new String(bytes, toCharset); return out; } catch (UnsupportedEncodingException e){ } return null; } public static String toString(String org, String toCharset){ return TFEncoding.toString(TFEncoding.toBytes(org, toCharset), toCharset); } }
使用
使用TFEncoding对象转换一下字符串的编码,因为字符串不能存储非“系统编码”数据,所以我们以BASE64编码结果对比。
a = "福哥"; byte[] bytes = TFEncoding.toBytes(a, "GBK"); b = base64Encoder.encode(bytes); String string = TFEncoding.toString(a, "GBK"); c = base64Encoder.encode(string); return "Org: "+a+"<br>Bytes: "+b+"<br>String: "+c;
可以看到同样的原始数据,同样的GBK编码,使用BASE64编码之后的结果完全不一样,证明了byte数组里存储的和String里存储的是不一样的内容了。
总结
福哥今天将研究了2天的关于Java语言编码转换的问题,得到了这些结论。大家可以感觉到Java是很严谨的语言,方方面面都在避免系统崩溃发生的可能,所以如果从类似PHP这种弱类型的脚本语言转过来的程序员会非常的不适应。