`

ISO8859-1字符集与其他字符集兼容性测试

 
阅读更多

ISO8859-1字符集中所有字符只占一个字节,8位,一个字节的编码空间为0x00-0xFF共256个字符。

 

ISO8859-1字符集中的部分(GBK GB2312 )或全部(UTF-8 UTF-16)字符在其他字符集中会存在,而且编码值还相同。

 

当把一个字符集中某个字符转换成另外一种字符集中的字符时,在转换过程中会有很大一部分字符在另一种字符集中是没有的(比如GBK繁体字符到GB2312),这时会使用另一种字符集中的问号代替这个未知字符,且编为63。但一般从多字节编码字符集(GBK GB2312 UTF-8 UTF-16)转换成单字节字符ISO8859-1时,是可以映射的,不会出现找不到可映射字符,因为每个字节的内容在ISO8859-1中都是找得到的,这就是为什么把一个 GBK、GB2312、UTF-8等编码的字符串以IS08859-1编码后,编码信息不会丢失的原因,最后还是可以还原成原来样子。

 

在Java里从一种字符转换成另一种字符集中的字符时,转换过程是要借助中间编码的,这个中间码就是Java语言本身所使用的编码——Unicode。现以ISO8859-1字符集中的¤字符转为GBK中的该字符为例:¤的ISO8859-1编码为A4,转换到Unicode字符集中后还是为A4(Unicode前256字个符与ISO8859-1是完全兼容的),然后由中间Unicode码映射到GBK字符集中相应字符,如果这个Unicode字符在GBK中存在,则使用对应的GBK编码,否则使用问号编码63代替,当然这一中间转换过程是由Java来帮我们实现的,最后我们的感觉就是由ISO8859-1直接转到了GBK编码。注,两种不同的编码中的相同的字符的编码不一定相同,这就是所谓的编码不兼容问题,比如说ISO8859-1字符¤的编码为A4,而映射到UTF-8后所对应的编码却为C2A4了。

 

从输出的附件可以看出(注,最好用记事本打开),GB2312、GBK、UTF-8字符集能兼容(兼容是指同一字符在两种不同字符集中都存在且编码还要相同)ISO8859-1的0x00-0x7F共128个字符。

 

ISO8859-1字符映射到GB2312、GBK字符集中后,能映射的字符这两种字符集基本上一样,只是在GBK字符集比GB2312多映射一个字符(B7·)。

 

ISO8859-1中编码大于0x7F的字符可全部映射到UTF-8字符,只是编码占用了两字节,但0x7F之后的字符只有一部分可以映射到GB2312、GBK字符集中。

 

Unicode、UTF-16编码完全兼容ISO8859-1字符集,即ISO8859-1中的字符在Unicode、UTF-16中存在,且编码完全相同。

 

编码大于0x7F的ISO8859-1字符,能映射到GB2312、GBK、UTF-8的都占两个字节,UTF-16就不用说了,肯定是两字节,只不过编码未变。

 

下面程序就是用来把ISO8859-1字符集映射到其他字符集的代码,它会把映射完后的字符分别输出到不同文件中,且无法映射(只ISO8859-1中某字符无法在其他字符集中找到)的字符不会输出到文件中。

 

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;

/**
 * ISO8859-1与其他字符兼容性测试
 * @author jzj
 */
public class ISOCharSet2OtherCharSet {
	public static void main(String[] args) throws UnsupportedEncodingException {
		try {
			String charSet = "GBK";
			toOtherCharSet(charSet);
			charSet = "UTF-8";

			toOtherCharSet(charSet);
			charSet = "GB2312";
			toOtherCharSet(charSet);

			charSet = "UTF-16";
			toOtherCharSet(charSet);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static void toOtherCharSet(String charSet)
			throws UnsupportedEncodingException, FileNotFoundException, IOException {
		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("e:/tmp/"
				+ charSet + ".txt"), charSet);
		osw.write("可映射字符 ISO8859-1 -> " + charSet + "\r\n");
		osw.write("\r\nISO8859-1=XX" + " " + charSet + "=XX\r\n");

		StringBuffer sb = new StringBuffer();
		//遍历256个ISO8859-1字符
		for (int i = 0; i <= 255; i++) {
			//ISO8859-1字符真实编码
			byte[] b = new byte[] { (byte) i };

			byte[] encodeArr = new String(b, "ISO8859-1").getBytes(charSet);
			short codeShort = encodeArr[0];

			/*
			 * 只有UTF-16才是固定4字节(前两字节为FE FF,后两个字节者是真真内容),其他编码可编码后为一个
			 * 字节,也可能为两个字节,且真实编码最多为两个字节。所以单字节ISO字符在其他字符集中可能为双字
			 * 节,如果为双字节时,取后两个字节(针对UTF-16,其他字符集最多为双字节)。
			 */
			if (encodeArr.length > 1) {
				codeShort = (short) ((encodeArr[encodeArr.length - 2] << 8) | (encodeArr[encodeArr.length - 1] & 0x00FF));
			}
			String gbkEncodeHex = short2Hex(codeShort);
			String isoEncodeHex = byte2Hex((byte) i);

			//如果ISO字符不能转换到指定的字符集中的字符时,会以问号替换,这里不输出不能映射的字符
			if (codeShort != 63 || (i == 63)) {
				osw.write(isoEncodeHex + "=" + new String(b, "ISO8859-1") + " ");
				osw.write(gbkEncodeHex + "=" + new String(encodeArr, charSet) + "\r\n");
			}
			//记录不兼容字符,即ISO8859-1中的字符在其他字符集中不存在,排除问题,因为问题肯定是兼容的
			if (codeShort == 63 && i != 63) {
				sb.append(isoEncodeHex);
				sb.append("=");
				sb.append(new String(b, "ISO8859-1"));
				sb.append("\r\n");
			}
		}
		if (sb.length() > 0) {
			osw.write("\r\n不兼容字符:\r\n" + sb);
		}
		osw.flush();
		osw.close();
	}

	/**
	 * 短整型转十六进制
	 * @param coding
	 * @return
	 */
	private static String short2Hex(short coding) {
		return Integer.toHexString(coding & 0x00FFFF | 0xFF0000).toUpperCase().substring(
				2, 6);
	}

	/**
	 * 字节型转十六进制
	 * @param coding
	 * @return
	 */
	private static String byte2Hex(byte coding) {
		return Integer.toHexString(coding & 0x00FF | 0xFF00).toUpperCase()
				.substring(2, 4);
	}
}

 

分享到:
评论

相关推荐

    grub4dos-V0.4.6a-2017-02-04更新

    1.skip_to()函数修改,对于引号里面的”\”使用以前的方法处理,保持兼容性。(chenall) 2.add variable @boot,add debug info。(chenall) 3.two variables boot_drive and install_partition can be preset to a ...

    winrar3.7 Beta8

    新的开关 -sc&lt;字符集&gt;[对象] 允许指定列表文件和压缩包注释文件的字符集。它代替 RAR 3.60 中的 -fcu 开关, -fcu 开关从支持的开关列表中移除。现在你需要指定 -scuc 代替 -fcu 使用 Unicode 注释。不像 -...

    WINRAR5.0正式注册版

    一个压缩文件发送给其他人,则需要考虑兼容性问题。你可以在压缩对话框中选择 "RAR" 替代 "RAR5" 选项创建 RAR 4.x 压缩文件来兼容以前版本的 WinRAR。 2. RAR 5.0 压缩算法的改变: a) 64 位 WinRAR 中最大的...

    《ASP.NET程序设计实用教程》配套资料-cd, ppt

    所有案例程序均来自课堂教学和工程实践,注重知识的兼容性和规范性。  依照ASP.NET编程体系,本书分成4部分,共11章。第1部分.NET应用开发基础,介绍了.NET应用开发体系与开发环境配置,以及C#语言程序设计基础...

    你必须知道的495个C语言问题

    int*array=&realarray[-1];我就可以把“array”当作下标从1 开始的数组。 函数和多维数组 6.18 当我向一个接受指针的指针的函数传入二维数组的时候,编译器报错了。 6.19 我怎样编写接受编译时宽度未知的二维...

    Oracle9i的init.ora参数中文说明

    在客户机和服务器上使用同一字符集时, 应以该字符集所定义的字符来衡量字符串。现有的列将不受影响。 值范围: BYTE 或 CHAR。 默认值: nls_length_semantics 的数据库字符集的字符所使用的度量单位。BYTE。 nls_...

    《你必须知道的495个C语言问题》

    书中列出了C用户经常问的400多个经典问题,涵盖了初始化、数组、指针、字符串、内存分配、库函数、C预处理器等各个方面的主题,并分别给出了解答,而且结合代码示例阐明要点。 《你必须知道的495个C语言问题》结构...

    c#学习笔记.txt

    这使得对字符串相等性的测试更为直观。字符串为 string 类型并可写成两种形式,即用引号引起来和用 @ 引起来。用引号引起来的字符串括在双引号 (") 内, 并且可以包含包括换码序列在内的任何字符用 @ 引起来的字符串...

    网管教程 从入门到精通软件篇.txt

    CHR:字符集(字体文件) CHT:ChartViem文件;Harvard Graphics矢量文件 CIF:Adaptec CD 创建器 CD映像文件 CIL:Clip Gallery下载包 CIM:SimCity 2000文件 CIN:OS/2改变控制文件用于跟踪INI文件中的变化 ...

    Excel公式与函数大辞典.宋翔(带书签高清文字版).pdf

    第1章 公式与函数基础 1 1.1 了解公式 1 1.1.1 公式的组成部分 1 1.1.2 数据类型及其相互转换 2 1.1.3 运算符及其优先级 3 1.1.4 普通公式与数组公式 5 1.1.5 单个单元格公式与多个单元格公式 5 1.1.6 Excel...

Global site tag (gtag.js) - Google Analytics