`

Java中的字符编码与解码

    博客分类:
  • Java
阅读更多
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;

import junit.framework.TestCase;

/** 
* 编码与解码测试 
* @author jzj 
*/
public class TestEncodeDecode extends TestCase {
	private char chineseChar = '中';
	private char englishChar = 'a';

	/** 
	* Java程序中的字符都是占用二个字节,因为 char 类型好比双字节的无符号整数 
	*/
	public void testCharToUnicode() {
		//十进制Uncode编码 
		System.out.println((int) chineseChar);//20013 
		System.out.println((int) englishChar);//97 

		//十六进制Uncode编码 
		System.out
				.println(Integer.toHexString((int) chineseChar).toUpperCase());//4E2D 
		System.out
				.println(Integer.toHexString((int) englishChar).toUpperCase());//61 

		//二进制Uncode编码 
		System.out.println(Integer.toBinaryString((int) chineseChar));//100111000101101 
		System.out.println(Integer.toBinaryString((int) englishChar));//1100001 
	}

	/** 
	* 不管是中文还是英文都还是其他字符,每个字符都是占用两个字节,英文字符的 
	* UTF-16编码与Unicode编码是一样的,只不过UTF-16在编码时会在码流前加上"FE FF"两个字节的内容, 
	* 表示字符是以UTF-16格式存储的,在读取时程序就会知道是UTF-16编码的字符 
	*/
	public void testCharToUTF16() {
		try {
			//--中文字符转UTF-16 
			byte[] encodeArr = String.valueOf(chineseChar).getBytes("UTF-16");
			//十进制编码输出 
			for (int i = 0; i < encodeArr.length; i++) {
				//-2 -1 78 45 
				System.out.print(encodeArr[i] + " ");
			}
			System.out.println();
			//十六进制编码输出 
			for (int i = 0; i < encodeArr.length; i++) {
				//FE FF 4E 2D 
				System.out.print(byteToHex(encodeArr[i]) + " ");
			}
			System.out.println();
			//所占字节数 
			System.out.println(encodeArr.length - 2);//2 

			//--英文字符转UTF-16 
			encodeArr = String.valueOf(englishChar).getBytes("UTF-16");
			//十进制编码输出 
			for (int i = 0; i < encodeArr.length; i++) {
				//-2 -1 0 97 
				System.out.print(encodeArr[i] + " ");
			}
			System.out.println();
			//十六进制编码输出 
			for (int i = 0; i < encodeArr.length; i++) {
				//FE FF 00 61 
				System.out.print(byteToHex(encodeArr[i]) + " ");
			}
			System.out.println();
			//所占字节数 
			System.out.println(encodeArr.length - 2);//2 

		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 以UTF-16写入文件时,也会把文件编码标志FE FF写入文件开头,但写入时不能编一码写一次文件,
	 * 因为这样每次以UTF-16编码时,都会生成编码标志,且写文件时也写入了,这样只需第一次写文件
	 * 时需要的标志却存入了多次,所以当以UTF-16存储字符时,最好一次性编码完成后再写入,或当字
	 * 符太多时,我们用OutputStreamWriter进行包装后可以方便地进行多次写入,而不会多次写入文
	 * 件编码标志,或者我们就用字节流来存,自已负责编码,但从第二次编码后写文件开始,手动去掉文
	 * 件编码标志后再存入也是可以的,只不过没有像直接以字符流多次写入那样方便了。
	 */
	public void testUTF16File() {
		try {
			//--字节流多次写错误
			byte[] encodeArr = String.valueOf(chineseChar).getBytes("UTF-16");
			OutputStream o = new FileOutputStream("e:/utf16.txt");
			o.write(encodeArr);
			encodeArr = String.valueOf(englishChar).getBytes("UTF-16");
			o.write(encodeArr);
			o.close();

			//--读
			BufferedReader br = new BufferedReader(new InputStreamReader(
					new FileInputStream("e:/utf16.txt"), "UTF-16"));
			//因为存储方法错误,所以导致读取时出现乱码,其实问号就是文件编码标志
			System.out.println(br.readLine());//中?a
			br.close();

			//--正确字节流多次写
			encodeArr = String.valueOf(chineseChar).getBytes("UTF-16");
			o = new FileOutputStream("e:/utf16.txt");
			o.write(encodeArr);
			encodeArr = String.valueOf(englishChar).getBytes("UTF-16");
			//从第二次开始写入时,不要把文件编码多次写入文件,这样存储会正确
			o.write(encodeArr, 2, encodeArr.length - 2);//中a
			o.close();

			//--读
			br = new BufferedReader(new InputStreamReader(new FileInputStream(
					"e:/utf16.txt"), "UTF-16"));
			System.out.println(br.readLine());//中a
			br.close();

			//--正确的字符流写
			OutputStreamWriter ow = new OutputStreamWriter(
					new FileOutputStream("e:/utf16.txt"), "UTF-16");
			ow.write(chineseChar);
			ow.write(englishChar);
			ow.close();

			//--读
			br = new BufferedReader(new InputStreamReader(new FileInputStream(
					"e:/utf16.txt"), "UTF-16"));
			System.out.println(br.readLine());//中a
			br.close();
		} catch (UnsupportedEncodingException e) {

			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 英文字符以UTF-8编码时只占一个字节或二字节(编码大于128小于256的英文字符),编码小于等于128的
	 * 字符UTF-8字符与Unicode编码兼容,中文字符以UTF-8编码时,占三个字节。
	 * 英文、中文使用的UTF-8编码规则模板分别是0xxxxxxx、1110xxxx 10xxxxxx 10xxxxxx
	 * 如"中"字的Unicode编码是4E2D。4E2D在0800-FFFF之间,所以要用上面的三字节规则模板,
	 * 将4E2D写成二进制是:0100 1110 0010 1101,将这个比特流按三字节模板的分段方法分为
	 * 0100 111000 101101,依次代替模板中的x,得到:1110-0100 10-111000 10-101101,
	 * 即 E4 B8 AD,这就是"中"字的UTF8的编码。
	 */
	public void testCharToUTF8() {
		try {
			//--中文字符转UTF-8
			byte[] encodeArr = String.valueOf(chineseChar).getBytes("UTF-8");
			//十进制编码输出
			for (int i = 0; i < encodeArr.length; i++) {
				//-28 -72 -83
				System.out.print(encodeArr[i] + " ");
			}
			System.out.println();
			//十六进制编码输出
			for (int i = 0; i < encodeArr.length; i++) {
				//E4 B8 AD
				System.out.print(byteToHex(encodeArr[i]) + " ");
			}
			System.out.println();
			//所占字节数
			System.out.println(encodeArr.length);//3
			//--英文字符转UTF-8
			encodeArr = String.valueOf(englishChar).getBytes("UTF-8");
			//十进制编码输出
			for (int i = 0; i < encodeArr.length; i++) {
				//97
				System.out.print(encodeArr[i] + " ");
			}
			System.out.println();
			//十六进制编码输出
			for (int i = 0; i < encodeArr.length; i++) {
				//61
				System.out.print(byteToHex(encodeArr[i]) + " ");
			}
			System.out.println();
			//所占字节数
			System.out.println(encodeArr.length);//1

		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 用Java程序入文件中以UTF-8编码方式存入字符时,是不会在文件头加上编码标志的。
	 * 但如果在windows中用记事本创建一个文件,并以UTF-8保存时,会在文件开开头写
	 * 入文件编码标志 EF BB BF 三个字节长度的编码标志,这时如果使用字节流方式读取
	 * 有编码标示的UTF-8文件时,会有问题,此时只能以字节流读出后去掉前三个字节内容
	 */
	public void testUTF8File() {
		try {
			//--字节流写
			byte[] encodeArr = String.valueOf(chineseChar).getBytes("UTF-8");
			OutputStream o = new FileOutputStream("e:/utf8.txt");
			o.write(encodeArr);
			encodeArr = String.valueOf(englishChar).getBytes("UTF-8");
			o.write(encodeArr);
			o.close();

			//--读
			BufferedReader br = new BufferedReader(new InputStreamReader(
					new FileInputStream("e:/utf8.txt"), "UTF-8"));
			System.out.println(br.readLine());//中a
			br.close();

			//--以字符流的方式读取windows记事本创建的有文件编码标志的UTF-8文件时错误
			br = new BufferedReader(new InputStreamReader(new FileInputStream(
					"e:/utf-8-2.txt"), "UTF-8"));
			System.out.println(br.readLine());//?中a
			br.close();

			//--以字节流读取有编码标志的UTF-8文件
			FileInputStream fi = new FileInputStream("e:/utf-8-2.txt");
			byte[] b = new byte[1024];
			int readCount = fi.read(b);
			//手动丢弃前三个字节的内容
			System.out.println(new String(b, 3, readCount - 3, "UTF-8"));//中a
			fi.close();
		} catch (UnsupportedEncodingException e) {

			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 英文字符以GBK编码时只占一个字节或二字节(编码大于128小于256的英文字符),编码小于等于128的
	 * 字符GBK字符与Unicode编码兼容,中文字符以GBK编码时,占
	 * 两个字节。
	 * GBK对中文编码时,每个字节的最高位都是一
	 */
	public void testCharToGBK() {
		try {
			//--中文字符转GBK
			byte[] encodeArr = String.valueOf(chineseChar).getBytes("GBK");
			//十进制编码输出
			for (int i = 0; i < encodeArr.length; i++) {
				//-42 -48
				System.out.print(encodeArr[i] + " ");
			}
			System.out.println();
			//十六进制编码输出
			for (int i = 0; i < encodeArr.length; i++) {
				//D6 D0
				System.out.print(byteToHex(encodeArr[i]) + " ");
			}
			System.out.println();
			//所占字节数
			System.out.println(encodeArr.length);//2
			//--英文字符转GBK
			encodeArr = String.valueOf(englishChar).getBytes("GBK");
			//十进制编码输出
			for (int i = 0; i < encodeArr.length; i++) {
				//97
				System.out.print(encodeArr[i] + " ");
			}
			System.out.println();
			//十六进制编码输出
			for (int i = 0; i < encodeArr.length; i++) {
				//61
				System.out.print(byteToHex(encodeArr[i]) + " ");
			}
			System.out.println();
			//所占字节数
			System.out.println(encodeArr.length);//1

		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}

	public void testCharFromUTF16() {
		try {
			byte[] encodeArr = String.valueOf(chineseChar).getBytes("UTF-16");
			System.out.println(new String(encodeArr, "UTF-16"));//中

			encodeArr = new byte[] { -0x2, -0x1, 0x4E, 0x2D };
			System.out.println(new String(encodeArr, "UTF-16"));//中
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}

	public static String byteToHex(byte b) {
		return Integer.toHexString((b & 0x000000FF) | 0xFFFFFF00).substring(6)
				.toUpperCase();
	}
}
分享到:
评论

相关推荐

    java使用URLDecoder和URLEncoder对中文字符进行编码和解码

    在Java编程语言中,`URLDecoder`和`URLEncoder`是两个非常重要的工具类,主要用于处理URL中的中文字符和其他特殊...理解它们的工作原理和使用方法,能帮助开发者避免编码解码过程中的常见问题,保证数据传输的准确性。

    字符编码解码工具字符编码,解码

    字符编码解码工具的设计往往注重易用性和兼容性,确保用户可以方便地处理各种编码格式的文件。例如,这样的工具可能会提供预设的编码选项供用户选择,或者通过分析文件内容自动检测其编码。同时,它还可能具备批量...

    tlv的java编码和解码

    - **源码包**:包含了实现TLV编码解码的Java源代码,可以学习和理解其内部实现逻辑。 - **Demo**:一个带有详细注释的示例程序,展示了如何使用这个库进行编码和解码操作,可以帮助开发者快速上手。 为了更好地利用...

    Java文本字符编码解码操作类 Escape.java源代码.rar

    在Java编程语言中,字符编码和解码是处理文本数据时不可或缺的部分,特别是在网络通信、文件存储或跨系统交互中。Escape.java源代码是专门设计用于处理文本字符的编码和解码操作的一个类。这个类的目标是确保无论...

    JAVA中文字符编码问题详解.doc

    在 JAVA 中,中文字符编码问题一直是让人头疼的问题,特别是在 WEB 应用中。网上的分析文章和解决方案都很多,但总是针对某些特定情况的。本文将详细解释 JAVA 中文字符编码问题的根源,并提供解决方案。 一、JAVA ...

    java_字符编码 Javajava_字符编码问题

    #### 二、Java中的字符串与字符编码 在 Java 中,`String` 类型是一种特殊的类型,它用来表示一系列字符的序列。Java 的 `String` 类内部是以 Unicode 编码存储的,这意味着每个字符都对应一个特定的 Unicode 码点...

    java使用Hex编码解码实现Aes加密解密功能示例

    在本文示例中,我们关注的是如何利用Java的Hex编码和解码来处理AES加密和解密的过程。 首先,让我们了解什么是Hex编码。Hex编码是一种将二进制数据转换为可打印字符的表示方式,每个字节被转换为两个十六进制数字...

    JAVA 转换字符编码工具

    本篇将围绕"JAVA 转换字符编码工具"这个主题,深入探讨字符编码的概念、Java中的字符编码API以及`ReadFile.java`这个可能的源码文件如何处理字符编码。 首先,我们需要理解字符编码的基本概念。常见的字符编码有...

    JAVA_字符编码

    总之,Java中的字符编码是一个复杂的主题,涉及Unicode、编码解码、I/O流的使用以及字符串处理等多个方面。了解这些知识对于编写跨平台、支持多语言的程序至关重要。通过深入学习和实践,开发者可以更好地处理各种...

    java和js相互base64编码解码

    `调用.txt`文件可能是测试这两种编码解码方法的简单脚本,它会调用Java和JavaScript中的函数,并比较结果是否一致,确保在不同环境下的Base64编码和解码是兼容的。 总之,Java和JavaScript中Base64编码和解码的实现...

    Java中文字符编码探究.pdf

    了解不同的字符编码方式和Java中的字符编码机制,可以帮助开发者更好地解决乱码问题,并提高开发效率。 在Web开发中,中文字符编码探究也非常重要。使用正确的字符编码方式,可以确保中文字符的正确显示和传输。...

    java的二维码编码与解码

    这个简单的Java二维码编码与解码说明文档提供了如何在Java程序中实现这一功能的步骤。 ### 1. 二维码编码 编码过程涉及到将信息转换为二维码图像。这里使用了`Qrcode_swetake.jar`库,它提供了生成二维码的API。...

    Java中的字符集编码入门(五)Java代码中的字符编码转换Part1.pdf

    Java中的字符编码转换是编程实践中一个至关重要的概念,尤其是在处理多语言环境和跨平台交互时。Java通过统一采用UTF-16编码格式在JVM内部处理字符,简化了字符操作的复杂性。UTF-16是一种变长的Unicode编码,它可以...

    java 字符集的解码方法

    在Java编程语言中,字符集(Charset)是用于表示文本数据的一系列规则,它定义了字符与二进制数据之间的映射关系。...以上就是关于Java字符集解码方法的详细说明,希望对您理解Java字符集处理有所帮助。

    java字符串编码转换

    #### 二、Java中的字符串与字符编码 在Java中,`String` 类型内部是以 Unicode 编码存储的。这意味着,所有的 `String` 对象本质上都是 Unicode 字符串。因此,当你在Java程序中创建一个 `String` 对象时,它默认...

    霍夫曼编码与解码的Java实现

    huffman的java实现 码表生成程序 可对任意“.txt”文件进行概率统计,显示字符及其概率对照表; 依概率编制Huffman码表,显示字符、对应概率及码字对照表。 编码程序 使用码表,对任意“.txt”进行Huffman编码; ...

    Java实现哈夫曼编码和解码

    需要注意的是,为了正确解码,编码过程中生成的编码表必须与解码过程共享。此外,为了防止数据被篡改,可以考虑在编码前加入校验机制,如计算校验和或使用哈希函数,确保数据在传输过程中未被修改。 总结来说,Java...

    java字符编码监听器

    Java字符编码监听器是Java Web开发中的一个重要概念,主要用于处理HTTP请求和响应中的字符编码问题。在Java Servlet规范中,提供了`SetCharacterEncodingFilter`这样的过滤器,用于确保请求参数和响应内容的正确编码...

    Java字符集和编码

    UTF-8(Unicode Transformation Format-8)是一种可变长度的字符编码格式,主要用于在网络中快速传输Unicode字符。UTF-8的基本原理是根据Unicode字符的范围,将其映射成不同长度的编码,具体规则如下: - 每个英文...

Global site tag (gtag.js) - Google Analytics