关于java编码

来源:互联网 发布:java工程师发展方向 编辑:程序博客网 时间:2024/05/16 00:28

 关于编码_1 :  

Java中将数据由UTF8转换成GB2312格式

UTF8 转换成GB2312 当我们在基于HTTP协议的JSP或Servlet的应用中获取数据或发送请求时,JVM会把输送的数据编码成UTF8格式。如果我们直接从HTTP流中 提取中文数据,提取的结果为“????”(可能更多问号),为转换成我们能够理解的中文字符,我们需要把UTF8转换成GB2312,借助ISO- 8859-1标准编码能够轻易的实现,下面的代码实现了这一功能:

byte [] b;
String utf8_value;
utf8_value = request.getParameter("NAME");//从HTTP流中取"NAME"的UTF8数据
b = utf8_value.getBytes("8859_1"); //中间用ISO-8859-1过渡
String name = new String(b, "GB2312"); //转换成GB2312字符

这是我做的一个项目程序的一段:
      byte[] b;
      String gbk_value;
      gbk_value=request.getParameter("address");//从HTTP流中取"name"的GBK数据(由于web.xml中过滤器设置默认编码为GBK,所以外网从UTF-8变为GBK)
      b=gbk_value.getBytes("GBK");//中间用GBK过渡,从GBK转换成GBK数组
      String address=new String(b,"utf-8");//转换成utf-8字符
      myform.setAddress(address);

在知道流长度的情况下将输入流转换成字节数组 Java中的输入流抽象类InputStream有int read(byte[] b, int off, int len)方法,参数中byte[] b是用来存放从InputStream中读取的数据,int off指定数组b的偏移地址,也就是数组b的起始下标,int len指定需要读取的长度,方法返回实际读取的字节数。

刚学Java 的朋友可能要说:先定义一个与流长度等长的字节数组,调用read方法,指定起始下标为0,指定读取长度与数组长度等长,不是一下子可以读出来了吗?说的 没错,笔者曾经也试着这样读取数据,但后来发现在读取网络数据时很不安全,我们想想在网络上获取数据可能并没那么流畅,数据流的传送可能会断断续续,所以 并不能保证一次就能读取全部数据,特别是在读取大容量数据时更是如此,所以我们必须在读取数据时检测实际读到的长度,如果没有读完已知长度的数据就应该再 次读取,以此循环检测,直到实际读取的长度累加与已知的长度相等,下面的代码实现了这一功能:

ServletInputStream inStream = request.getInputStream(); //取HTTP请求流
int size = request.getContentLength(); //取HTTP请求流长度
byte[] buffer = new byte[size]; //用于缓存每次读取的数据
byte[] in_b = new byte[size]; //用于存放结果的数组
int count = 0;
int rbyte = 0;
while (count < size) {
//循环读取
rbyte = inStream.read(buffer); //每次实际读取长度存于rbyte中
for(int i=0;i.....
......

在不知道流长度的情况下将输入流转换成字节数组 前面介绍了已知流长度的情况下的转换方法,那么当我们不知道流有多长时,也就是说不能确定转换后的字节数组有多大时,该怎么处理呢?笔者查看了JDK文档 之后发现ByteArrayOutputStream有一个byte[] toByteArray()方法,该方法会自动创建一个字节数组,然后返回。于是就巧妙的用ByteArrayOutputStream来作中间过渡实现 转换,其它处理跟上面所介绍已知长度的情况差不多。假设需要被转换的流已经放在inStream里了,我们可以用如下的代码实现这一功能:

ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
byte[] buff = new byte[100]; //buff用于存放循环读取的临时数据
int rc = 0;

while ((rc = inStream.read(buff, 0, 100)) > 0) {
swapStream.write(buff, 0, rc);
}
byte[] in_b = swapStream.toByteArray(); //in_b为转换之后的结果

 

 关于编码_2 : 

GBK转成ISO8859_1,再转回GBK没有问题,但是为什么GBK转成UTF-8,再转回GBK就是乱码了?! 

  String   str="中国";  
  String   str1=new   String(str.getBytes("GBK"),"ISO8859_1");  
  String   str2=new   String(str1.getBytes("ISO8859_1"),"GBK");  
  System.out.println("Received2:   "   +   str2);   //   这儿能输出中国  
   
  String   str="中国";  
  String   str1=new   String(str.getBytes("GBK"),"UTF-8");  
  String   str2=new   String(str1.getBytes("UTF-8"),"GBK");  
  System.out.println("Received2:   "   +   str2);//   这儿输出乱码

 因为ISO8859_1是一种很特殊的编码,每一个字节在这种编码上都有对应的字符,因此任意编码都可以转成这个 再变回原来的编码但是其他大部分编码都不具备这种性质,因此这种过程总的来说是不可逆的   
 ps:ISO8859_1(又叫latin1)的这种性质经常用来做在不支持某一编码的平台上进行存储信息