`

【Java基础专题】编码与乱码(03)----String的toCharArray()方法

 
阅读更多
	package example.encoding;

import java.io.UnsupportedEncodingException;

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

    /** *//**
     * 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);

        GetCharTest tester = new GetCharTest();
        tester.getCharWithDefaultEncoding(content);
        tester.getCharWithGivenEncoding(content, "ISO-8859-1");
        tester.getCharWithGivenEncoding(content, "GBK");
        tester.getCharWithGivenEncoding(content, "UTF-8");
    }

    /** *//**
     * Gets the char with default encoding.
     * 
     * @param content the content
     * 
     * @return the char with default encoding
     */
    public void getCharWithDefaultEncoding(String content) {
        System.out.println("\nGet characters with default encoding\n");
        printCharArray(content);
    }

    /** *//**
     * Gets the char with given encoding.
     * 
     * @param content the content
     * @param encoding the encoding
     * 
     * @return the char with given encoding
     */
    public void getCharWithGivenEncoding(String content, String encoding) {
        System.out.println("\nGet characters with given encoding : " + encoding
                + "\n");
        try {
            String encodedString = new String(content.getBytes(), encoding);
            printCharArray(encodedString);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    /** *//**
     * Prints the char array.
     * 
     * @param inStr the in str
     */
    public void printCharArray(String inStr) {
        char[] charArray = inStr.toCharArray();

        for (int i = 0; i < inStr.length(); i++) {
            byte b = (byte) charArray[i];
            short s = (short) charArray[i];
            String hexB = Integer.toHexString(b).toUpperCase();
            String hexS = Integer.toHexString(s).toUpperCase();
            StringBuffer sb = new StringBuffer();

            // print char
            sb.append("char[");
            sb.append(i);
            sb.append("]='");
            sb.append(charArray[i]);
            sb.append("'\t");

            // byte value
            sb.append("byte=");
            sb.append(b);
            sb.append(" \\u");
            sb.append(hexB);
            sb.append('\t');

            // short value
            sb.append("short=");
            sb.append(s);
            sb.append(" \\u");
            sb.append(hexS);
            sb.append('\t');

            // Unicode Block
            sb.append(Character.UnicodeBlock.of(charArray[i]));

            System.out.println(sb.toString());
        }
        System.out.println("\nCharacters length: " + charArray.length);
    }

}

 

【1】在中文平台下,测试的结果如下:
System default encoding --- GBK
System default language --- zh

 

Get characters with default encoding

char[0]='中' byte=45 \u2D short=20013 \u4E2D CJK_UNIFIED_IDEOGRAPHS
char[1]='文' byte=-121 \uFFFFFF87 short=25991 \u6587 CJK_UNIFIED_IDEOGRAPHS

Characters length: 2

Get characters with given encoding : ISO-8859-1

char[0]='?' byte=-42 \uFFFFFFD6 short=214 \uD6 LATIN_1_SUPPLEMENT
char[1]='?' byte=-48 \uFFFFFFD0 short=208 \uD0 LATIN_1_SUPPLEMENT
char[2]='?' byte=-50 \uFFFFFFCE short=206 \uCE LATIN_1_SUPPLEMENT
char[3]='?' byte=-60 \uFFFFFFC4 short=196 \uC4 LATIN_1_SUPPLEMENT

Characters length: 4

Get characters with given encoding : GBK

char[0]='中' byte=45 \u2D short=20013 \u4E2D CJK_UNIFIED_IDEOGRAPHS
char[1]='文' byte=-121 \uFFFFFF87 short=25991 \u6587 CJK_UNIFIED_IDEOGRAPHS

Characters length: 2

Get characters with given encoding : UTF-8

char[0]='?' byte=-3 \uFFFFFFFD short=-3 \uFFFFFFFD SPECIALS
char[1]='?' byte=-3 \uFFFFFFFD short=-3 \uFFFFFFFD SPECIALS
char[2]='?' byte=-3 \uFFFFFFFD short=-3 \uFFFFFFFD SPECIALS
char[3]='?' byte=-3 \uFFFFFFFD short=-3 \uFFFFFFFD SPECIALS

Characters length: 4

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


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

Get characters with default encoding

char[0]='?' byte=45 \u2D short=20013 \u4E2D CJK_UNIFIED_IDEOGRAPHS
char[1]='?' byte=-121 \uFFFFFF87 short=25991 \u6587 CJK_UNIFIED_IDEOGRAPHS

Characters length: 2

Get characters with given encoding : ISO-8859-1

char[0]='?' byte=63 \u3F short=63 \u3F BASIC_LATIN
char[1]='?' byte=63 \u3F short=63 \u3F BASIC_LATIN

Characters length: 2

Get characters with given encoding : GBK

char[0]='?' byte=63 \u3F short=63 \u3F BASIC_LATIN
char[1]='?' byte=63 \u3F short=63 \u3F BASIC_LATIN

Characters length: 2

Get characters with given encoding : UTF-8

char[0]='?' byte=63 \u3F short=63 \u3F BASIC_LATIN
char[1]='?' byte=63 \u3F short=63 \u3F BASIC_LATIN

Characters length: 2

【结论】


和getBytes(encoding)不同,toCharArray()返回的是"自然字符"。但是这个"自然字符"的数目和内容却是由原始的编码方式决定的。来看看里面是如何进行字符串的操作的:
 
 String encodedString = new String(content.getBytes(), encoding);
 char[] charArray = inStr.toCharArray();

可以看到系统首先对原始字符串按照默认的编码方式进行编码,得到一个字节数组,然后按照指定的新的编码方式进行解码,得到新的编码后的字符串。再转换成对应的字符数组。

由于在中文平台下,默认的字符集编码是GBK,于是content.getBytes()得到的是什么呢?就是下面这4个字节:

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

如果新的encoding是GBK,那么经过解码后,由于一个字符用2个字节表示。于是最终的结果就是:
 char[0]='中' --- byte[0] + byte[1]
 char[1]='文' --- byte[2] + byte[3]

如果新的encoding是ISO-8859-1,那么经过解码后,由于一个字符用1个字节表示,于是原来本应该2个字节一起解析的变成单个字节解析,每个字节都代表了一个汉字字符的一半。这一半的字节在ISO-8859-1中找不到对应的字符,就变成了"?"了,最终的结果:
 char[0]='?' ---- byte[0]
 char[1]='?' ---- byte[1]
 char[2]='?' ---- byte[2]
 char[3]='?' ---- byte[3]

如果新的encoding是UTF-8,那么经过解码后,由于一个字符用3个字节表示,于是原来4个字节的数据无法正常的解析成UTF-8的数据,最终的结果也是每一个都变成"?"。
 char[0]='?' ---- byte[0]
 char[1]='?' ---- byte[1]
 char[2]='?' ---- byte[2]
 char[3]='?' ---- byte[3]

如果是在英文平台下,由于默认的编码方式是Cp1252,于是content.getBytes()得到的字节都是被截去一半的残留字符,所以我们看到在英文平台下,不论指定的encoding是GBK、UTF-8,其结果和ISO-8859-1都是一样的。

记住:

这个方法再次证明了String的getBytes()方法的危险性,如果我们使用new String(str.getBytes(), encoding)对字符串进行重新编码解码时,我们一定要清楚str.getBytes()方法返回的字节数组的长度、内容到底是什么,因为在接下来使用新的encoding进行编码解码时,Java并不会自动地对字节数组进行扩展以适应新的encoding。而是按照新的编码方法直接对该字节数组进行解析。

于是结果就像上面的例子一样,同样是4个原始字节,有些每2个一组进行解析,有些每个一组进行解析,有些每3个一组进行解析。其结果就只能看那种编码方式合适了。

分享到:
评论

相关推荐

    String与单字符的常用方法(charAt(),toCharArray())

    charat方法 String与单字符的常用方法(charAt(),toCharArray())String与单字符的常用方法(charAt(),toCharArray())String与单字符的常用方法(charAt(),toCharArray())String与单字符的常用方法(charAt(),toCharArray...

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

    1、char[]与string之间的转换 //string 转换成 Char[] string str=hello; char[] arr=str.ToCharArray(); //Char[] 转换成 string string str1 = new string(arr); 2、byte[]与string之间的转化 string str = 你好...

    StringAPI.java

    boolean equalsIgnoreCase(String anotherString):与equals方法类似,忽略大小写 String concat(String str):将指定字符串连接到此字符串的结尾。 等价于用“+” String substring(int beginIndex):返回一个新...

    完整版Java全套入门培训课件 Java基础 06-集合(共24页).pptx

    String类部分方法 char charAt(int index) int length() char[] toCharArray(); int indexOf(String str); boolean endsWith(String str); String[] split(String reg); String substring(int index); String(char[]...

    mongo-java-driver最新jar.zip

    mongo-java-driver3.0以上jar压缩包大全 try { //1.连接池相关选项配置 MongoClientOptions options=MongoClientOptions.builder() .connectionsPerHost(poolSize) .minConnectionsPerHost(minpoolsize) ...

    打败所有黑客的加密算法

    那么所有排列的数量就与你原始明文的长度密切相关,比如10位,所有可能就是P10的全排列。不同密码,可能加密出同样的结果。但是如果把一个字符按64位或256位处理,短短的10位字符,已经不再只有P10的全排列个结果。 ...

    java字符串转数组.docx

    使用String类的toCharArray()方法: 这个方法将字符串转换为字符数组。 示例:char[] charArray = str.toCharArray(); 使用String类的split()方法: 这个方法将字符串根据指定的分隔符分割成字符串数组。 示例:...

    Java语言程序设计(第3版)第06章-字符串.pptx

    6.1.1 字符串转换为数组 Java语言程序设计(第3版) char[] toCharArray() byte[] getBytes() Java语言程序设计(第3版)第06章-字符串全文共31页,当前为第8页。 6.1.1 字符串比较 Java语言程序设计(第3版) 不能使用"=...

    Java中char数组(字符数组)与字符串String类型的转换方法

    主要介绍了Java中char数组(字符数组)与字符串String类型的转换方法,涉及Java中toCharArray与valueOf方法的使用技巧,需要的朋友可以参考下

    汉字转拼音

    t1 = src.toCharArray(); String[] t2 = new String[t1.length]; HanyuPinyinOutputFormat t3 = new HanyuPinyinOutputFormat(); t3.setCaseType(HanyuPinyinCaseType.LOWERCASE); t3.setToneType...

    java代码获取myeclipse注册码.txt

    String verTime = new StringBuilder("-").append(new java.text.SimpleDateFormat("yyMMdd").format(cal.getTime())).append("0").toString(); String type = "YE3MP-"; String need = new StringBuilder...

    人民币小写转大写(Java 实现)

    //ChangeRMB.java /** * * programmed by HuangHeliang * 2009.04.15 10:20:51 * */ //package com.avtech.hhl; import java.io.*; public final class ChangeRMB { //每个数字对应的大写 private static ...

    Java 2实用教程(第三版)实验指导与习题解答

    Java 2实用教程(第三版)实验指导与习题解答 清华大学出版社 (编著 耿祥义 张跃平) 实验模版代码 建议使用文档结构图 (选择Word菜单→视图→文档结构图) 上机实践1 初识Java 4 实验1 一个简单的应用程序 ...

    Java优化编程(第2版)

    Java优化编程(第2版)通过丰富、完整、富有代表性的实例,展示了如何提升Java应用性能,并且给出了优化前与优化后的Java应用程序的性能差别,以实际的实例与数字告诉你,为什么不可以这么做,应该怎么做,深入分析...

    java字符串操作大全

    java字符串操作大全,适合初学者,浅显易懂 部JAVA字符串操作 2008-07-11 15:39:42| 分类: JAVA | 标签: |字号大中小 订阅 . JAVA字符串的方法 String a = "53c015"; //Integer.parseInt(s, radix) radix设置为...

    Java中反转功能的的实现

    import java.util.Scanner; /* * 反转功能 * */ public class Day13StringBuffer09 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入一个数字:...

    java写的将字符串中的中文转化为拼音等一系列方法

    char[] input = inputString.trim().toCharArray(); String output = ""; try { for (int i = 0; i ; i++) { if (java.lang.Character.toString(input[i]).matches("[\\u4E00-\\u9FA5]+")) { ...

    经典java组合算法源码--TryCombination(算法源码)

    char[] chArray=str.toCharArray(); System.out.println("对字符数组进行组合:C(4,4)"); Combination strCombination1=new Combination(chArray.length); while(strCombination1.hasMore()){ int[] ...

    JAVA——linux

    String[] blue = ("01,02,03,04,05,06,07," + "08,09,10,11,12,13,14,15,16").split(","); boolean[] used = new boolean[red.length]; Random r = new Random(); //System.out.println(Arrays.toString(red)...

    java编写的验证码

    用java编写的验证码,希望对大家有用 g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255))); g.fillRect(0, 0, width, height); String strs = "0123456789...

Global site tag (gtag.js) - Google Analytics