`
liuguxing
  • 浏览: 92666 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

String.getBytes()方法中的中文编码问题

    博客分类:
  • JAVA
 
阅读更多
String的getBytes()方法是得到一个字串的字节数组,这是众所周知的。但特别要注意的是,本方法将返回该操作系统默认的编码格式的字节数组。如果你在使用这个方法时不考虑到这一点,你会发现在一个平台上运行良好的系统,放到另外一台机器后会产生意想不到的问题。
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两种编码格式的字节数组,看看会有什么结果:

class TestCharset  
{
    public static void main(String[] args)  
    { 
        new TestCharset().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)
分享到:
评论

相关推荐

    Java中的String类getBytes()方法详解与实例

    在本文中,我们学习了Java String类的getBytes()方法,它允许将字符串转换为字节数组,并且可以指定字符编码方式。通过实例和代码演示了使用平台默认字符编码和指定UTF-8、ISO-8859-1字符编码的情况。getBytes()方法...

    C#(.net)中按字节数截取字符串最后出现乱码问题的解决

    Encoding.UTF8.GetBytes采用的是utf-8编码。这样当然是乱码。尤其出现中文时候。 对这类数据处理当然要用统一的编码来处理。下面话不多说了,来一起看看详细的介绍吧 例子:1 string msg= Encoding.UTF8....

    C#_string_byte数组转换解析

    C# string byte数组间转换所涉及的方法是什么呢?让我们来看看具体的内容: C# string byte数组转换之string类型转成byte[]: byte[] byteArray = System.Text.Encoding.Default.GetBytes ( str ); 反过来,byte[]转...

    JS实现对中文字符串进行utf-8的Base64编码的方法(使其与Java编码相同)

    本文实例讲述了JS实现对中文字符串进行utf-8的Base64编码的方法。分享给大家供大家参考,具体如下: 要进行编码的字符串:“select 用户名 from 用户” 使用JAVA进行编码,Java程序: String sql = select 用户名 ...

    struts2上传插件(中文编码冲突解决)

    解决Struts2上传时候使用UTF-8的冲突问题... * 对于请求流,使用的ISO-8859-1编码方式进行,如果发现请求内容中出现名称乱码,请使用new String(str.getBytes("ISO-8859-1"),"GBK")进行编码转换。 包里面已经含有源代码

    史上最全的java基础总结大全

    public static void main(String[] args) { //编码解码1:默认编码 String str1 = "你好"; byte[] buf1 = str1.getBytes();//默认解码:Unicode,四个字节 //编码解码2:指定编码 String str2 = "你好"; ...

    C# char[]与string byte[]与string之间的转换详解

    1、char[]与string之间的转换 //string 转换成 Char[] string str=hello; char[] arr=str.ToCharArray(); //Char[] 转换成 string string str1 = new ...//string 转换成 byte[] (字符串是用哪种编码生成的byte[]

    短信发送代码

    /// 去掉在进行Unicode格式编码中,两个字节中的"-",例如:00-21,变成0021 /// 将整条短信内容的长度除2,保留两位16进制数 /// public static string Encoding(string value) { Encoding encoding = System...

    Java get 提交乱码处理方法

    解决办法  1、在后台获取时采用  String b = new String(request....  3、如果上述方法还不能解决问题  在前台处理汉字 java.net.URLEncoder.ecode("中文","GBK");//前面是要处理的中文字符  eg: win

    DownLoadUtil.java

    public static String getFileName(String agent, String filename) throws UnsupportedEncodingException { if (agent.contains("MSIE")) { // IE浏览器 filename = URLEncoder.encode...

    sshz中文乱码解决方法

    String userTmp0 = new String(user.getUsername().getBytes("ISO-8859-1"),"GBK"); 将iso-8859-1 转成gbk编码 上面这种方式是强制转的。。 下面的方式是解决ssh乱码的 struts2中文乱码解决方案 1.在struts.xml...

    2020年SpringMVC面试题,看这篇就足够了

    1. 什么是SpringMVC? SpringMVC是一种基于 Java 的实现MVC设计模型的请求驱动类型的轻量级Web框架,属于Spring框架的一个...String userName = new String(request.getParamter("userName").getBytes("ISO8859-1"),"u

    PDU短信发送编码程序(C#)

    程序中的sp是SerialPort类型的对象,在System.IO.Ports命名空间下 //手机号码转换为pdu模式 private string telc(string MobileNum) { int tl; string ltem, rtem, ttem; int ti; ttem = ""; tl = ...

    c#中文gbk编码查询示例代码

    代码如下:private void button_Inquriy_Click(object sender, EventArgs e) { if ... byte[] bytes = Encoding.GetEncoding(“GB2312”).GetBytes(strInquiry); String strResult = String.Empty; foreach (b

    java licence生成例子

    java中使用公钥加密私钥解密原理. KeyGenerater类: public class KeyGenerater { private byte[] priKey; private byte[] pubKey; public void generater() { try { KeyPairGenerator keygen = KeyPairGenerator ...

    jspsmartupload上传下载,已修改过源代码!

    如果表单项中填写了中文,一样会有乱码问题。看了下jspsmartupload的源码,改了两个地方,现在可以没有乱码问题了。 第一个地方,修改类SmartUpload中的upload()方法 // //这次用jspSmartUpload做文件上传下载, /...

    字符串各种编码转换 Scanner 、String

    此例子是一个字符串转各种编码的demo,编码格式是已经定义好的,当然你也可以扩充,使用时只需要构造它的对象然后调用对应的转换格式的方法即可,很简单的!

    java 爬网 程序 示例

    // keyword = new String(param.getBytes("gb2312"), "ISO-8859-1"); // } catch (UnsupportedEncodingException e1) { // // TODO Auto-generated catch block // e1.printStackTrace(); // } // ...

    全文修改编码

    全文修改编码,request.setCharacterEncoding("gb2312"); 或者单个修改 out.print("用户名:"+new String(request.getParameter("name").getBytes("iso-8859-1"),"gb2312")+" ");

    JavaScript 字符编码规则

    并不需要转为UTF-8,这时可用[escape] 当源与目标页字符集不同时,需要对源字符转为目标字符,为统一可考虑使用UTF-8 new String(request.getParameter(“PARAM_NAME”).getBytes(“源页编码”), “UTF-8”)

Global site tag (gtag.js) - Google Analytics