String的getBytes()方法是得到一个字串的字节数组,这是众所周知的。但特别要注意的是,本方法将返回该操作系统默认的编码格式的字节数组。如果你在使用这个方法时不考虑到这一点,你会发现在一个平台上运行良好的系统,放到另外一台机器后会产生意想不到的问题。比如下面的程序:

class TestCharset { 
public static void main(String[] args) { 
new TestCharset().execute(); 
private void execute() { 
String s = "Hello!你好!"; 
byte[] bytes = s.getBytes();
System.out.println("bytes lenght is:" + bytes.length); 
}

在一个中文WindowsXP系统下,运行时,结果为:

bytes lenght is:12

但是如果放到了一个英文的UNIX环境下运行:

$ java TestCharset bytes lenght is:9

如果你的程序依赖于该结果,将在后续操作中引起问题。为什么在一个系统中结果为12,而在另外一个却变成了9了呢?上面已经提到了,该方法是和平台(编码)相关的。

在中文操作系统中,getBytes方法返回的是一个GBK或者GB2312的中文编码的字节数组,其中中文字符,各占两个字节。而在英文平台中,一般的默认编码是“ISO-8859-1”,每个字符都只取一个字节(而不管是否非拉丁字符)。

Java中的编码支持

Java是支持多国编码的,在Java中,字符都是以Unicode进行存储的,比如,“你”字的Unicode编码是“4f60”,我们可以通过下面的实验代码来验证:

class TestCharset { 
public static void main(String[] args) { 
char c = '你'; 
int i = c; 
System.out.println(c); 
System.out.println(i); 
}

不管你在任何平台上执行,都会有相同的输出:

20320

20320就是Unicode “4f60”的整数值。其实,你可以反编译上面的类,可以发现在生成的.class文件中字符“你”(或者其它任何中文字串)本身就是以Unicode编码进行存储的:

char c = '/u4F60'; ... ...

即使你知道了编码的编码格式,比如:

javac -encoding GBK TestCharset.java

编译后生成的.class文件中仍然是以Unicode格式存储中文字符或字符串的。使用String.getBytes(String charset)方法

所以,为了避免这种问题,我建议大家都在编码中使用String.getBytes(String charset)方法。下面我们将从字串分别提取ISO-8859-1和GBK两种编码格式的字节数组,看看会有什么结果:

package org.bruce.file.handle.experiment;  

class TestCharset3 {
public static void main(String[] args) {
new TestCharset3().execute();
} private void execute() {
String s = "Hello!你好!";
byte[] bytesISO8859 = null;
byte[] bytesGBK = null;
try {
bytesISO8859 = s.getBytes("iso-8859-1");
bytesGBK = s.getBytes("GBK");
} catch (java.io.UnsupportedEncodingException e) {
e.printStackTrace();
}
System.out.println("-------------- /n 8859 bytes:");
System.out.println("bytes is: " + arrayToString(bytesISO8859));
System.out.println("hex format is:" + encodeHex(bytesISO8859));
System.out.println();
System.out.println("-------------- /n GBK bytes:");
System.out.println("bytes is: " + arrayToString(bytesGBK));
System.out.println("hex format is:" + encodeHex(bytesGBK));
} public static final String encodeHex(byte[] bytes) {
StringBuffer buff = new StringBuffer(bytes.length * 2);
String b;
for (int i = 0; i < bytes.length; i++) {
b = Integer.toHexString(bytes[i]);
// byte是两个字节的, 而上面的Integer.toHexString会把字节扩展为4个字节
buff.append(b.length() > 2 ? b.substring(6, 8) : b);
buff.append(" ");
}
return buff.toString();
} public static final String arrayToString(byte[] bytes) {
StringBuffer buff = new StringBuffer();
for (int i = 0; i < bytes.length; i++) {
buff.append(bytes[i] + " ");
}
return buff.toString();
}
}

执行上面程序将打印出:

-------------- 8859 bytes: bytes is: 72 101 108 108 111 33 63 63 63 
hex format is:48 65 6c 6c 6f 21 3f 3f 3f 
--------------  GBK bytes: bytes is: 72 101 108 108 111 33 -60 -29 -70 -61 -93 -95 
hex format is:48 65 6c 6c 6f 21 c4 e3 ba c3 a3 a1

可见,在s中提取的8859-1格式的字节数组长度为9,中文字符都变成了“63”,ASCII码为63的是“?”,一些国外的程序在国内中文环境下运行时,经常出现乱码,上面布满了“?”,就是因为编码没有进行正确处理的结果。

而提取的GBK编码的字节数组中正确得到了中文字符的GBK编码。字符“你”“好”“!”的GBK编码分别是:“c4e3”“bac3”“a3a1”。得到了正确的以GBK编码的字节数组,以后需要还原为中文字串时,可以使用下面方法:

new String(byte[] bytes, String charset)
   mysql 不支持 unicode,所以比较麻烦。
   将 connectionString 设置成 encoding 为 gb2312
   String connectionString
   = "jdbc:mysql://localhost/test?useUnicode=true&characterEncoding=gb2312";
  
  测试代码:
   String str = "汉字";
   PreparedStatement pStmt = conn.prepareStatement("INSERT INTO test VALUES (?)");
   pStmt.setString(1,str);
   pStmt.executeUpdate();
  
  数据库表格:
   create table test (
   name char(10)
   )
  
  
  连接 Oracle Database Server
  -------------------------------------------------------------------------------
   在把汉字字符串插入数据库前做如下转换操作:
   String(str.getBytes("ISO8859_1"),"gb2312")
  
  测试代码:
   String str = "汉字";
   PreparedStatement pStmt = conn.prepareStatement("INSERT INTO test VALUES (?)");
   pStmt.setString(1,new String(str.getBytes("ISO8859_1"),"gb2312");
   pStmt.executeUpdate();
  
  
  Servlet
  -------------------------------------------------------------------------------
   在 Servlet 开头加上两句话:
   response.setContentType("text/html;charset=UTF-8");
   request.setCharacterEncoding("UTF-8");
  
  JSP
  -------------------------------------------------------------------------------
 @Test
public void testBytes(){
//字节数
//中文:ISO:1 GBK:2 UTF-8:3
//数字或字母: ISO:1 GBK:1 UTF-8:1
String username = "中";
try {
//得到指定编码的字节数组 字符串--->字节数组
byte[] u_iso=username.getBytes("ISO8859-1");
byte[] u_gbk=username.getBytes("GBK");
byte[] u_utf8=username.getBytes("utf-8");
System.out.println(u_iso.length);
System.out.println(u_gbk.length);
System.out.println(u_utf8.length);
//跟上面刚好是逆向的,字节数组---->字符串
String un_iso=new String(u_iso, "ISO8859-1");
String un_gbk=new String(u_gbk, "GBK");
String un_utf8=new String(u_utf8, "utf-8");
System.out.println(un_iso);
System.out.println(un_gbk);
System.out.println(un_utf8);
//有时候必须是iso字符编码类型,那处理方式如下
String un_utf8_iso=new String(u_utf8, "ISO8859-1");
//将iso编码的字符串进行还原
String un_iso_utf8=new String(un_utf8_iso.getBytes("ISO8859-1"),"UTF-8");
System.out.println(un_iso_utf8); } catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

测试结果:

1
 2
 3
 ?
 中
 中
 ä¸­
 中

从转载的文章摘:

乱码原因:为什么使用ISO8859-1编码再组合之后,无法还原"中"字呢,其实原因很简单,因为ISO8859-1编码的编码表中,根本就没有包含汉字字符,当然也就无法通过"中".getBytes("ISO8859-1");来得到正确的"中"字在ISO8859-1中的编码值了,所以再通过new String()来还原就无从谈起了.

有时候,为了让中文字符适应某些特殊要求(如http header头要求其内容必须为iso8859-1编码),可能会通过将中文字符按照字节方式来编码的情况,如:
String s_iso88591 = new String("中".getBytes("UTF-8"),"ISO8859-1"),这样得到的s_iso8859-1字符串实际是三个在ISO8859-1中的字符,在将这些字符传递到目的地后,目的地程序再通过相反的方式String s_utf8 = new String(s_iso88591.getBytes("ISO8859-1"),"UTF-8")来得到正确的中文汉字"中".这样就既保证了遵守协议规定、也支持中文.

转自:http://blog.csdn.net/yang3wei/article/details/7381578          http://blog.csdn.net/techbirds_bao/article/details/8555449

java String.getBytes()编码问题——String.getBytes(charset)的更多相关文章

  1. [转]String.getBytes()和new String()

    在Java中,String.getBytes(String decode)方法会根据指定的decode编码返回某字符串在该编码下的byte数组表示,如 byte[] b_gbk = "中&q ...

  2. 通过Java编码获取String分行字符串的内容

    代码案列: import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException ...

  3. new String(request.getParameter("userID").trim().getBytes("8859_1"))的含义是什么?

    new String(request.getParameter("userID").trim().getBytes("8859_1")) request.get ...

  4. java String字符串编码类型转换

    /** * 前后端数据乱码问题 * 解决办法1: * 乱码原因:一编一解码型不一致导致. * [main description] * @param {[type]} String[] args [d ...

  5. java源码解析之String类(二)

    上一节主要介绍了String类的一些构造方法,主要分为四类 无参构造器:String(),创建一个空字符串"",区别于null字符串,""已经初始化,null并 ...

  6. java 上传MultipartFile和String post请求

    /** * POST Multipart Request * @Description: * @param requestUrl 请求url * @param requestText 请求参数 * @ ...

  7. Java入门 - 语言基础 - 14.String类

    原文地址:http://www.work100.net/training/java-string.html 更多教程:光束云 - 免费课程 String类 序号 文内章节 视频 1 概述 2 创建字符 ...

  8. 菜鸡的Java笔记 第十四 String 类常用方法

    /*String 类常用方法    将所有String类的常用方法全部记下来,包括方法名称,参数作用以及类型    一个成熟的编程语言,除了它的语法非常完善之外,那么也需要提供有大量的开发类库     ...

  9. Java学习笔记19(String类)

    String代表字符串,在Java中,所有的字符串字面值都作为此类的实例实现 字符串的特点以及简单的原理分析: package demo; /* * String类的特点: * 所有的"&q ...

随机推荐

  1. Android 之 Intent(意图)

    Intent是 Android中重要的桥梁之一,它分为显式意图和隐式意图.接下来分别针对这两种意图进行讲解. 显式意图:通过指定一组数据或动作,激活应用内部的 activity:(相比隐式意图,此做法 ...

  2. iOS之UI--转场动画

    1.什么是转场动画?    就是从一个场景转换到另一个场景,像导航控制器的push效果,就是一个转场.    2.如何创建转场动画    创建转场动画    CATransition *anim = ...

  3. Hive安装与配置(靠谱亲测)

     Hive是hadoop生态环境的组成之一.通过Hive,可以使得直接用SQL操作HDFS.最大的好处就是让熟悉SQL,但是不了解JAVA的数据分析师使用.其机制就是一个将SQL语言转化为MapRed ...

  4. git 一般的开发流程中的代码管理

    一般的开发流程中的代码管理 1. 从版本库中下载代码 git clone ssh://wenbin@192.168.1.3:29418/mustang-web 2. 针对某个feature(比如ins ...

  5. MongoDB学习笔记——聚合操作之group,distinct,count

    单独的聚合命令(group,distinct,count) 单独聚合命令 比aggregate性能低,比Map-reduce灵活度低:但是可以节省几行javascript代码,后面那句话我自己加的,哈 ...

  6. Showing progress bar in a status bar pane

    在工具卡显示进度条,原文链接:http://www.codeproject.com/Articles/35/Showing-progress-bar-in-a-status-bar-pane 1.构造 ...

  7. Web Application Project is configured to use IIS. Unable to access the IIS metabase.(配置为使用IIS Web应用程序xxxx项目。无法访问IIS元数据库。)

    这几天重装系统,装了win10,居然用vs2013打开项目出现下面这个提示错误,搞了很久才知道原因: Even though I am an administrator on the machine, ...

  8. Merge Two Sorted Lists

    Merge Two Sorted Lists https://leetcode.com/problems/merge-two-sorted-lists/ Merge two sorted linked ...

  9. Vertica 项目常用代码

    1.查看目录下面有多少文件数 ls -l |grep "^-"|wc -l 思路很明显了,ls后通过grep进行过滤判断是文件还是文件夹, 如果是判断文件夹,可以使用ls -l | ...

  10. 使用EntityFramework6完成增删查改和事务

    使用EntityFramework6完成增删查改和事务 上一节我们已经学习了如何使用EF连接数据库,并简单演示了一下如何使用EF6对数据库进行操作,这一节我来详细讲解一下. 使用EF对数据库进行操作, ...