`

【Java基础专题】编码与乱码(02)---String的getBytes([encoding])方法

 
阅读更多
package example.encoding;

import java.io.UnsupportedEncodingException;

/** *//**
 * The Class GetBytesTest.
 */
public class GetBytesTest {

    /** *//**
     * The main method.
     * 
     * @param args the arguments
     */
    public static void main(String args[]) {
        
        String content = "中文";
        String defaultEncoding = System.getProperty("file.encoding");
        String defaultLnaguage = System.getProperty("user.language");
        System.out.println("System default encoding --- " + defaultEncoding);
        System.out.println("System default language --- " + defaultLnaguage);

        GetBytesTest tester = new GetBytesTest();

        byte[] defaultBytes = tester.getBytesWithDefaultEncoding(content);
        tester.printBytes(defaultBytes);

        byte[] iso8859Bytes = tester.getBytesWithGivenEncoding(content,
                "ISO-8859-1");
        tester.printBytes(iso8859Bytes);

        byte[] gbkBytes = tester.getBytesWithGivenEncoding(content, "GBK");
        tester.printBytes(gbkBytes);

        byte[] utfBytes = tester.getBytesWithGivenEncoding(content, "UTF-8");
        tester.printBytes(utfBytes);

    }

    /** *//**
     * Gets the bytes with default encoding.
     * 
     * @param content the content
     * 
     * @return the bytes with default encoding
     */
    public byte[] getBytesWithDefaultEncoding(String content) {
        System.out.println("\nEncode with default encoding\n");
        byte[] bytes = content.getBytes();
        return bytes;
    }

    /** *//**
     * Gets the bytes with given encoding.
     * 
     * @param content the content
     * @param encoding the encoding
     * 
     * @return the bytes with given encoding
     */
    public byte[] getBytesWithGivenEncoding(String content, String encoding) {
        System.out.println("\nEncode with given encoding : " + encoding + "\n");
        try {
            byte[] bytes = content.getBytes(encoding);
            return bytes;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
    }

    /** *//**
     * Prints the bytes.
     * 
     * @param bytes the bytes
     */
    public void printBytes(byte[] bytes) {
        for (int i = 0; i < bytes.length; i++) {
            System.out.print(" byte[" + i + "] = " + bytes[i]);
            System.out
                    .println(" hex string = " + Integer.toHexString(bytes[i]));
        }
    }

}

 【1】在中文平台下,测试结果如下:


System default encoding --- GBK
System default language --- zh

Encode with default encoding

 byte[0] = -42 hex string = ffffffd6
 byte[1] = -48 hex string = ffffffd0
 byte[2] = -50 hex string = ffffffce
 byte[3] = -60 hex string = ffffffc4

Encode with given encoding : ISO-8859-1

 byte[0] = 63 hex string = 3f
 byte[1] = 63 hex string = 3f

Encode with given encoding : GBK

 byte[0] = -42 hex string = ffffffd6
 byte[1] = -48 hex string = ffffffd0
 byte[2] = -50 hex string = ffffffce
 byte[3] = -60 hex string = ffffffc4

Encode with given encoding : UTF-8

 byte[0] = -28 hex string = ffffffe4
 byte[1] = -72 hex string = ffffffb8
 byte[2] = -83 hex string = ffffffad
 byte[3] = -26 hex string = ffffffe6
 byte[4] = -106 hex string = ffffff96
 byte[5] = -121 hex string = ffffff87

【2】在英文平台下,测试结果如下:


System default encoding --- Cp1252
System default language --- en

 

Encode with default encoding

 byte[0] = 63 hex string = 3f
 byte[1] = 63 hex string = 3f

Encode with given encoding : ISO-8859-1

 byte[0] = 63 hex string = 3f
 byte[1] = 63 hex string = 3f

Encode with given encoding : GBK

 byte[0] = -42 hex string = ffffffd6
 byte[1] = -48 hex string = ffffffd0
 byte[2] = -50 hex string = ffffffce
 byte[3] = -60 hex string = ffffffc4

Encode with given encoding : UTF-8

 byte[0] = -28 hex string = ffffffe4
 byte[1] = -72 hex string = ffffffb8
 byte[2] = -83 hex string = ffffffad
 byte[3] = -26 hex string = ffffffe6
 byte[4] = -106 hex string = ffffff96
 byte[5] = -121 hex string = ffffff87

【结论】


getBytes()、getBytes(encoding)函数的作用是使用系统默认或者指定的字符集编码方式,将字符串编码成字节数组。

 

在中文平台下,默认的字符集编码是GBK,此时如果使用getBytes()或者getBytes("GBK"),则按照GBK的编码规则将每个中文字符用2个byte表示。所以我们看到"中文"最终GBK编码结果就是: -42 -48 -50 -60 。-42和-48代表了"中"字,而"-50"和"-60"则代表了"文"字。

在中文平台下,如果指定的字符集编码是UTF-8,那么按照UTF-8对中文的编码规则:每个中文用3个字节表示,那么"中文"这两个字符最终被编码成:-28 -72 -83、-26 -106 -121两组。每3个字节代表一个中文字符。

在中文平台下,如果指定的字符集编码是ISO-8859-1,由于此字符集是单字节编码,所以使用getBytes("ISO-8859-1")时,每个字符只取一个字节,每个汉字只取到了一半的字符。另外一半的字节丢失了。由于这一半的字符在字符集中找不到对应的字符,所以默认使用编码63代替,也就是?。

在英文平台下,默认的字符集编码是Cp1252(类似于ISO-8859-1),如果使用GBK、UTF-8进行编码,得到的字节数组依然是正确的(GBK4个字节,UTF-8是6个字节)。因为在JVM内部是以Unicode存储字符串的,使用getBytes(encoding)会让JVM进行一次Unicode到指定编码之间的转换。对于GBK,JVM依然会转换成4个字节,对于UTF-8,JVM依然会转换成6个字节。但是对于ISO-8859-1,则由于无法转换(2个字节--->1个字节,截取了一半的字节),所以转换后的结果是错误的。

相同的平台下,同一个中文字符,在不同的编码方式下,得到的是完全不同的字节数组。这些字节数组有可能是正确的(只要该字符集支持中文),也可能是完全错误的(该字符集不支持中文)。

记住:

不要轻易地使用或滥用String类的getBytes(encoding)方法,更要尽量避免使用getBytes()方法。因为这个方法是平台依赖的,在平台不可预知的情况下完全可能得到不同的结果。如果一定要进行字节编码,则用户要确保encoding的方法就是当初字符串输入时的encoding。

 

分享到:
评论

相关推荐

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

    前言 最近需要用到按字节数截取字符串。在网上找了很多方法。... string msg= Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(strcode)); 例子:2 string strcode=我是小明; byte[] buffer=Encoding.UTF8.Ge

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

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

    sshz中文乱码解决方法

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

    C#_string_byte数组转换解析

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

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

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

    jforum-2.5.0修正版

    jforum-2.5.0官方原版存在bug,导致版面分类与管理乱码,但分布主题与回复中文正常. 安装方法: ... ... this.addParameter(name, new String(values[i].getBytes(containerEncoding), encoding)); } }

    c# 加密和解密相关代码

    string类的ToCharArray 方法用来将字符串中的字符复制到Unicode 字符数组,该方法有两种重载形式,本 实例中用到的它的重载形式如下: public char[] ToCharArray() 参数说明 返回值:元素为此字符串的各字符的...

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

    7. <id name="fileId" type="java.lang.String" column="FILE_ID"> 8. 9. 10. 11. type="org.springframework.orm.hibernate3.support.BlobByteArrayType" 12. column="FILE_CONTENT" lazy="true"/> 13. …//...

    C#中压缩字符串

    byte[] data = System.Text.Encoding.UTF8.GetBytes(param); //byte[] data = Convert.FromBase64String(param); MemoryStream ms = new MemoryStream(); Stream stream = new ICSharpCode.SharpZipLib.BZip2....

    jsp九大内置对象

     字符串用ISO-8859-1进行编码,并将编码存发岛一个字节数组中,然后再将这个数组转化为字符串对象  即可。如下:  String textContent=request.getParameter("boy")  byte b[]=textContent.getBytes("ISO-...

    Bootstrap分页

    String userName = new String(username.getBytes("ISO-8859-1"),"UTF-8");//处理乱码 Map&lt;String, Object&gt; map = new HashMap&lt;String, Object&gt;(); username=(username==null)?"":username; map.put...

    CDMA 猫用AT命令发中文短信(C#)

    转载请注明来源 代码如下: void SendCHNSms(string content,string phone) { //中文CDMA发送,UNICODE编码字节 byte[] b = Encoding.BigEndianUnicode.GetBytes(content); //CDMA的AT命令手机号码前面不能加86,...

Global site tag (gtag.js) - Google Analytics