`
casec12
  • 浏览: 45072 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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)
分享到:
评论
1 楼 uqortbsa 2010-10-14  
非常有用,谢谢

相关推荐

    IO流的使用,自己的心得

    byte writeStringToBytes[] = writeString.getBytes(); byte temp[] = new byte[tempLength]; //需要几次写入 if(writeStringToBytes.length%tempLength==0) each = writeStringToBytes.length/...

    net学习笔记及其他代码应用

    int i= System.Text.Encoding.Default.GetBytes(strTmp).Length; int j= strTmp.Length; 以上代码执行完后,i= j= 答:i=13,j=10 28.SQLSERVER服务器中,给定表 table1 中有两个字段 ID、LastUpdateDate,ID表示...

    超级有影响力霸气的Java面试题大全文档

    当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。 20、abstract class和interface有什么区别? ...

    c# 加密和解密相关代码

    本实例实现时主要用到了string 类的ToCharArray 方法和Convert 类的ToChar 方法,下面分别对它们进行 详细介绍。 (1)string类的ToCharArray 方法 string类的ToCharArray 方法用来将字符串中的字符复制到Unicode ...

    Android程序技术:文件存储和JSON解析.pptx

    将应用程序中的数据以文件方式存储到设备的内部,当创建的应用程序被卸载时,其内部存储文件也随之被删除。 文件存储简介 File Storage Overview 内部存储 文件存储简介 File Storage Overview 内部存储—写入 ...

    httpRequest

    httprequet的post,get方法的应用。(HttpWebRequest)WebRequest.Create(strUrlLine); 15. httpReq.Method = strHttpMethod; 16. httpReq.ContentType = "application/x-www-form-urlencoded"; if (String.Compare...

    jsp九大内置对象

    如果要动态改变这换个属性值来响应客户,就需要使用Response对象的setContentType(String s)方法来改变contentType的属性值。  格式:response.setContentType(String s);  参数s可取text/html,application/x-ms...

    《Web应用技术》实验

    byte a []=name.getBytes("ISO-8859-1"); name=new String(a); String sex = request.getParameter("sex"); String address = request.getParameter("address"); String tel = request.getParameter("tel"); ...

    C#与PHP的md5计算结果不同的解决方法

    这个 API 是当时给 Lyra 应用做激活用的,遂打开 Lyra 试了下,却发现一切正常,于是可以排除服务端的问题 放出导致错误的源码(来自 MSDN): public string CalculateMD5Hash(string input) { // step 1, ...

    java 面试题 总结

    当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。 17、abstract class和interface有什么区别? 声明方法...

    javaBean实验报告.doc

    public String getname() { try { byte b[]=username.getBytes("ISO-8859-1"); username=new String(b); return username; } catch(Exception e) { return username; } } public String getpsw() { try{ byte c[]=...

    调用API

    httpRequest.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(new System.Text.ASCIIEncoding().GetBytes(usernamePassword)));复制代码6. 发起POST请求: httpRequest.Method = "POST"; ...

    C#全能速查宝典

    2.1.3 Appllication类——提供管理应用程序的静态方法 126 2.1.4 CancelButton属性——设置取消按钮 128 2.1.5 Computer类——提供操作计算机组件的属性 129 2.1.6 ComputerInfo类——获取计算机信息 130 2.1.7 ...

    [S036] MD5算法.rar

    byte[] strTemp = s.getBytes(); MessageDigest mdTemp = MessageDigest.getInstance("MD5"); mdTemp.update(strTemp); byte[] md = mdTemp.digest(); int j = md.length; char str[] = new char...

    ssh(structs,spring,hibernate)框架中的上传下载

     其中save(FileActionForm fileForm)方法,将封装在fileForm中的上传文件保存到数据库中,这里我们使用FileActionForm作为方法入参,FileActionForm是Web层的表单数据对象,它封装了提交表单的数据。将...

    Android开发人员不得不收集的代码

    getBytes : 缓存中读取字节数组 getString : 缓存中读取 String getJSONObject : 缓存中读取 JSONObject getJSONArray : 缓存中读取 JSONArray getBitmap : 缓存中读取 Bitmap getDrawable : 缓存中读取 Drawable ...

    flex:Flex协议,客户端和服务器

    柔性Flex是具有客户端和服务器jar库的简单协议/框架,...值始终是ByteString(byte []) 支持心脏呼吸协议以检测活动连接自动重新连接例子客户端示例: ByteString value = ByteString.copyFrom("bytes".getBytes());

    微信开发框架wechat4j

    wechat4j是一个帮助你开发微信应用的jar包,使用它,你开发微信公众号应用只需要几秒钟的时间,完全不用关注太细节的东西。 ##wechat4j快速开始 可以去下载wechat4j示例项目[wechat4jDemo]...

    udp 和tcp结合视频监控系统.zip

    queue.Enqueue(this.Encoding.GetBytes(datagram)); waiter.Set(); return this; } private void WorkThread() { while (IsRunning) { waiter.WaitOne(); waiter.Reset(); while (queue....

    实验三Socket通信实验报告.doc

    掌握客户/服务器(C/S)应用的工作方式; 3. 学习网络中进程之间通信的原理和实现方法; 4. 理解单播、组播和广播的原理并比较其不同之处; 5. 要求本机既是客户端又是服务器端; (2)实验内容 所编写的程序应具有...

Global site tag (gtag.js) - Google Analytics