`

【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个一组进行解析。其结果就只能看那种编码方式合适了。

分享到:
评论

相关推荐

    Java判断字符串是否含有乱码实例代码

    本文将介绍通过实例代码如何判断一个字符串是否含有乱码,并通过编写的Java方法来实现此功能。 首先,我们需要明确什么情况下的字符串可以被认为是“乱码”。通常,乱码指的是由于字符编码不正确而导致显示出来的...

    GBK与UTF-8之间的转换

    但是,这种方法存在一些问题,例如,使用new String(tmp.getBytes("GBK"), "UTF-8")这种方法将GBK编码的字符串转换成UTF-8编码的字符串时,可能会出现乱码的问题。 出现这种问题的原因是,因为客户端使用GBK编码,...

    JAVA字符串编解码问题[定义].pdf

    这意味着,如果原始字符串是通过某种特定编码创建的,`toCharArray()`返回的“自然字符”可能与直接从Unicode编码的`String`转换的`char[]`不同。 总结来说,Java字符串的编解码是一个需要注意编码类型和平台依赖性...

    java字符之间的转化

    在Java编程语言中,字符之间的转化是常见的操作,特别是在处理字符串、字符数组或者与外部数据交互时。Java提供了丰富的API和内置类型来支持这些转化。本文将深入探讨Java中字符间转换的关键知识点。 首先,Java中...

    java中英文字符串截取

    在Java编程语言中,处理字符串是一项常见的任务,尤其是在进行数据清洗、格式化或者解析文本时。中文和英文字符由于编码方式的不同,在处理时需要特别注意,尤其是当涉及到字符串的截取时。本文将深入探讨如何在Java...

    JAVA字符串编解码问题.pdf

    在Java中,所有的字符串(String类型)都是以Unicode编码存储的,这是一种广泛支持的多字节字符集,能够表示世界上几乎所有的字符。 1. **JVM与Unicode**: Java虚拟机(JVM)内部的字符串(String)实际上是无编码的...

    java中文转拼音0积分0积分

    Java String类默认使用Unicode编码,与UTF-8兼容,因此在读写文件或网络通信时,要注意保持一致的编码方式,避免乱码问题。 2. **Java I/O操作** 读取文件(如COPYING.txt、使用说明.txt、README.txt、CHANGELOG....

    解决JDK1.6下的Base64报错问题

    在Java开发过程中,有时我们可能需要使用到Base64编码,这是一种将二进制数据转换为可打印ASCII字符的机制,常用于在网络上传输或存储数据。然而,在JDK 1.6版本中,Base64相关的类并不内置在标准库中,这可能会导致...

    commons-codec-1.9

    6. **CharEncoding**:提供了一种确定和验证字符编码的方法,避免了常见的乱码问题。 三、使用示例 以下是一些基本的使用示例,展示了如何在1.9版本中使用Apache Commons Codec: ```java import org.apache....

    desJS和JAVA加解密

    本文将详细介绍`DES`(Data Encryption Standard)加解密技术以及如何在前端JS与后端Java之间进行配合使用,以解决加密后可能出现的乱码问题和特殊字符问题。 首先,`DES`是一种对称加密算法,由美国国家标准局于...

    java实现的汉字转五笔功能实例

    Java中的`Charset`类提供了`new String(byte[], charsetName)`和`getBytes(charsetName)`方法进行编码转换。 - 在处理字符串时,要确保编码的一致性,避免乱码问题。 5. **代码实现**: - 从给出的部分代码来看,...

    自己写的简繁通代码,用JAVA实现

    在转换过程中,可以使用Java的`String`类提供的`toCharArray()`方法将字符串转换为字符数组,然后遍历这个数组,对于每个字符,检查映射表中是否存在对应的繁体字符,如果存在则替换,否则保留原样。最后,将处理过...

    检查字符串中字符出现的次数(包含汉字)

    2. **定义类与方法**: - 定义了一个名为`TestStringBuffer`的类。 - 类中包含一个`getkey`方法,用于获取用户的输入。此方法创建了一个`Scanner`对象,并使用`nextLine()`方法读取用户输入的一行文本。 3. **...

    Android zip4j压缩、解压、加解密的示例代码

    //设置编码格式,避免中文文件名乱码 zipParameters = new ZipParameters(); zipParameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); //选择DEFLATE压缩方法 zipParameters.setCompressionLevel...

Global site tag (gtag.js) - Google Analytics