`
izuoyan
  • 浏览: 9220434 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

手机中文码制问题的一点理解

阅读更多

作者:风过回廊 文章来源:http://www.sf.org.cn

论坛上很多的帖子都是在讨论手机上的中文码制问题,我也曾经被此类的问题所困扰,并且得到了不少热心的朋友的帮助。通过一端时间的资料查找和测试学习,我对这个问题有一点点自己的理解和想法,不敢敝帚自珍,特分享给大家,由于本人水平有限,况且也是业余的开发爱好者,没有专业的理论学习水平,所以请大家就文章中的一些错误予以谅解并提出批评,本篇的文章仅做抛砖引玉,非常的欢迎大家的跟贴,我们群策群力,共同来解决这个问题。:)

论坛上很多的帖子都是在讨论手机上的中文码制问题,我也曾经被此类的问题所困扰,并且得到了不少热心的朋友的帮助。通过一端时间的资料查找和测试学习,我对这个问题有一点点自己的理解和想法,不敢敝帚自珍,特分享给大家,由于本人水平有限,况且也是业余的开发爱好者,没有专业的理论学习水平,所以请大家就文章中的一些错误予以谅解并提出批评,本篇的文章仅做抛砖引玉,非常的欢迎大家的跟贴,我们群策群力,共同来解决这个问题。:)

手机里面的字符串基本上都是采用的UTF-8的编码法。
而我们在PC机器上所采用的基本上都是ASCII和unicode编码法
ASCII编码法是单字节的编码方法,只能表示256个字符,英文字母是足够了
但是无法表示汉字
unicode是双字节的编码法,可以用来表示汉字,但是却对于一般的英文字母浪费了太多的空间(至少面对于手机的存储是这样的)。
UTF-8就是专门手机这种嵌入式设备的新的编码法,他的特点是,传统的ASCII字符还是以一个字节来表示的,但是如果字符不属于ASCII字符集时,就用两至三个位来表示。
在 0x0001-0x007F之间的字符(传统的ASCII字符)用一个位来表示
0 | bits0-6
在 0x000以及在0x0080-0x07FF之间的字符使用下面来表示:
1 | 1 | 0 | bits 6-10 | 1 | 0 | bits 0-5
如果虚拟机看到这样的一个字符的话,虚拟机会把第一个字节最前头的110以及第二个字节的前头的10拿掉把剩下的位重新组合成一个2字节的数位来表示字符:
00000 | bits 6-10 | bits 0-5
同理,0x0800 - 0xFFFF的字符表示:
1 | 1 | 1 | 0 | bits 12-15 | 1 | 0 | bits 6-11 | 1 | 0 | bits 0-5
也可以用同样的方法重新组合成一个两个字节的字符串来
特别需要注意的是kjava中的null字符也使用两个字节来表示而不是一个字节:)

当然英文字符串在UTF-8编码法中不会出什么问题(默认为标准的ACSII编码机制)主要的问题还是中文,我个人在Kjava的手机开发中中文字符串所碰到的问题主要分为以下几类:
1.rms数据库读写的问题;
2.在jad中书写游戏中文名称;
3.网络传输中中文问题(kxml传输的解码);
4.部分的模拟器也不支持中文.
这几个部分是在手机开发中,中文经常出错的险区,通常的表现形式是乱码:)

1.了解到了UTF-8码的基本原理就非常的有利于我们解决码制转化的问题
在转化UTF-8码中我处理的方法是这样的

//向数据库中写入中文
String appt3 = "中文字符";
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeUTF(appt3);
byte[] bytes3 = bos.toByteArray();
rs.addRecord(bytes3, 0, bytes3.length);

//从数据库中读出中文
byte b3[] = rs.getRecord(dbid);
DataInputStream dis=new DataInputStream(new ByteArrayInputStream(b3));
String chinastring = dis.readUTF();

writeUTF() 和 readUTF() 分别是DataOutputStream 和 DataInputStream对象的的方法,他们提供了一个由从Unicode到UTF-8的相互转化的途径。
仔细看看midp的说明文档,可以看到以下内容
writeUTF() :
First, two bytes are written to the output stream as if by the writeShort method giving the number of bytes to follow. This value is the number of bytes actually written out, not the length of the string. Following the length, each character of the string is output, in sequence, using the UTF-8 encoding for the character.If no exception is thrown, the counter written is incremented by the total number of bytes written to the output stream. This will be at least two plus the length of str, and at most two plus thrice the length of str.

当然我们也可以自己来手工的编写代码,把中文字符串转化成byte[]再放入RMS,取出时转成String即可。
这里借用bingo_guan的方法(bingo_guan,请不要介意呀 :)),当然了这段代码也非常的设计模式化 :) hehe,这个类也可用于文本文件操作。

/**
* Title:
* Description: unicode字串转换工具
* Copyright: Copyright (c) 2003

* Company: CC Studio
* @author Bingo
* @version 1.0
*/

public class UnicodeString
{

public UnicodeString()
{
}

public static String byteArrayToString(byte abyte0[], int i)
{
StringBuffer stringbuffer = new StringBuffer("");
for(int j = 0; j < i; )
{
int k = abyte0[j++]; //注意在这个地方进行了码制的转换
if(k < 0)
k += 256;
int l = abyte0[j++];
if(l < 0)
l += 256;
char c = (char)(k + (l << 8));//把高位和低位数组装起来
stringbuffer.append(c);
}

return stringbuffer.toString();
}

public static String byteArrayToString(byte abyte0[])
{
return byteArrayToString(abyte0, abyte0.length);
}

public static byte[] stringToByteArray(String s)
{
int i = s.length();
byte abyte0[] = new byte[i << 1];
int j = 0;
for(int k = 0; k < i; k++)
{
char c = s.charAt(k);
abyte0[j++] = (byte)(c & 0xff); //每一个位按位转化
abyte0[j++] = (byte)(c >> 8);
}

return abyte0;
}
}

2.其次,在jad和manifest中的中文字(比如说游戏的名字)实际上也都是 UTF-8编码,这一块也是经常出问题的险区,我建议还是自己手工转化成UTF-8的编码写在上面,否则的话,如果你用unicode码制写入中文的话,在模拟器或者实际设备上就有无法识别而导致程序不能执行的危险。所以大家在编辑jad文件的时候应该尽量小心才好 :) 特别注意,wtk的jad自动生成的工具并不支持直接在jad和manifest输入UTF-8格式,所以手工修改这一步恐怕是免不了的了 :(。

3.不同的手机其实支持的默认码制也是不一样的,这也是经常出现问题的关键,CLDC的系统属性"microedition.encoding"定义了设备的默认字符编码,它的值可以使用System.getProperty方法取得。我们也可以转化成相关的支持的编码机制来实际的运行我们的程序。
这种方式我们通常会用在有关手机中文问题传输中,因为在联网时的手机是不确定的。以下我给出一段实例代码,和大家探讨一下这个问题。

服务器到客户端:
------------------------------------------------------------------
下面代码是服务器端把字符写到Client端,经过gbEncoding()方法,所有的字符编码成:\uXXXX.
-----------------------------------------------------------------

代码:-------------------------------------------------------------
/**
* Write the String data
*
* @param out
* @param value
*/


public static void writeUnicode(final DataOutputStream out, final String value) throws ActionException {
try {
final String unicode = StringFormatter.gbEncoding( value );
final byte[] data = unicode.getBytes();
final int dataLength = data.length;

System.out.println( "Data Length is: " + dataLength );
System.out.println( "Data is: " + value );
out.writeInt( dataLength ); //先写出字符串的长度
out.write( data, 0, dataLength ); //然后写出转化后的字符串
} catch (IOException e) {
throw new ActionException( IMDefaultAction.class.getName(), e.getMessage() );
}
}

----------------------------------------------------------------------
以下代码是gbEncoding()方法,把双字节字符转换成\uXXXX,ASIIC码在前面补00。
----------------------------------------------------------------------
/**
* This method will encode the String to unicode.
*
* @param gbString
* @return
*/

代码:--------------------------------------------------------------------------------
public static String gbEncoding( final String gbString ) {
char[] utfBytes = gbString.toCharArray();
String unicodeBytes = "";
for( int byteIndex = 0; byteIndex < utfBytes.length; byteIndex ++ ) {
String hexB = Integer.toHexString( utfBytes[ byteIndex ] );
if( hexB.length() <= 2 ) {
hexB = "00" + hexB;
}
unicodeBytes = unicodeBytes + "\\u" + hexB;
}
System.out.println( "unicodeBytes is: " + unicodeBytes );
return unicodeBytes;
}
--------------------------------------------------------------------------------

----------------------------------------------------------------------
在客户端收到服务器的数据,先将其一个一个字符解码。双字节显示正常。
----------------------------------------------------------------------

代码:--------------------------------------------------------------------------------
/**
* This method will decode the String to a recognized String
* in ui.
* @param dataStr
* @return
*/
private StringBuffer decodeUnicode( final String dataStr ) {
int start = 0;
int end = 0;
final StringBuffer buffer = new StringBuffer();
while( start > -1 ) {
end = dataStr.indexOf( "\\u", start + 2 );
String charStr = "";
if( end == -1 ) {
charStr = dataStr.substring( start + 2, dataStr.length() );
} else {
charStr = dataStr.substring( start + 2, end);
}
char letter = (char) Integer.parseInt( charStr, 16 ); // 16进制parse整形字符串。
buffer.append( new Character( letter ).toString() );
start = end;
}
return buffer;
}
--------------------------------------------------------------------------------

----------------------------------------------------------------------
客户端到服务器:
----------------------------------------------------------------------
客户端使用下面方法把手机端的字符编码成ISO-8859-1,传给服务器。
----------------------------------------------------------------------

代码:--------------------------------------------------------------------------------
/**
* write the String data
* @param value
* @param outData
*/
private void writeSjis(DataOutputStream outData, String value) {
try {
byte[] data = null;
// data = ( value ).getBytes( "UTF-8" );
data = ( value ).getBytes( "ISO8859_1" );
outData.writeInt(data.length);
outData.write(data, 0, data.length);

System.out.println(" data.length: " + data.length);
System.out.println(" data.value: " + value);
} catch (Exception ex) {
System.out.println(" write error ");
ex.printStackTrace();
}
}
--------------------------------------------------------------------------------

----------------------------------------------------------------------
服务器端收到客户端字符流,是用下面方法将其转为UTF-8,以后的操作都是基于UTF-8编码。SQLServer可能会由于内吗不通有不同的变换,所以存取数据库是还要是具体的DB内码作相应的处理。
----------------------------------------------------------------------

代码:--------------------------------------------------------------------------------
/**
*
* @param iso
* @return
*/
public static String isoToUtf( final String iso ) {
String utfString = iso;
if( iso != null ) {
try {
utfString = new String( iso.getBytes( "ISO-8859-1" ), "UTF-8" );
} catch ( UnsupportedEncodingException e ) {
utfString = iso;
}
} else {
utfString = "";
}
return utfString;
}

只要手机支持unicode的gb2312编码,应该都可以显示正常。

4。至于某些手机的模拟器不支持中文(譬如nokia 60系列),那真的没有办法了,只有等待他的中文版本出来了 呵呵,:)我的信箱是 zhaofei8009@wellhope.sh,非常的欢迎大家来信共同讨论这个问题,也非常的希望交到技术上的朋友.

共同努力,一起进步!

分享到:
评论

相关推荐

    第1关:汉字国标码转区位码实验.txt

    根据提供的文件信息,我们可以推断出这是一份与计算机硬件设计相关的实验文档,特别是涉及到汉字国标码到区位码转换的部分。...理解这一点对于深入学习汉字编码以及如何通过硬件逻辑实现特定功能至关重要。

    java汉字转五笔码,oracle函数转五笔码

    五笔字型是一种流行的中文输入法,它将汉字拆分为不同的部分,每个部分对应一个或多个字母,这些字母组合起来就构成了汉字的五笔码。五笔码通常由四个或五个字母组成,如“王”字的五笔码是“wng”,“大”字的五笔...

    汉字区位码(HZQUM)

    由于汉字数量庞大且结构复杂,如何有效地将汉字转化为计算机可以理解的形式,成为了中文信息技术发展的一个重要挑战。汉字区位码作为一种编码方式,解决了这一问题,使得计算机能够高效地处理汉字信息。 #### 汉字...

    华为手机查询S/N码、IMEI码、产品识别码工具 解锁工具

    首先,我们要理解“S/N码”(Serial Number,序列号)、“IMEI码”(International Mobile Equipment Identity,国际移动设备身份码)以及“产品识别码”。这些都是手机的唯一标识符,对于设备管理和售后服务具有...

    汉字区位码。汉字区位码

    汉字区位码是一种用于汉字编码的...尽管如此,了解汉字区位码对于理解汉字编码历史和计算机处理汉字的基本原理仍然具有一定的价值。尤其是在处理早期的文本数据或者特定的历史系统时,汉字区位码的知识可能会派上用场。

    ST7920 GB中文字型码表

    开发人员在使用ST7920进行汉字显示时,需要正确地查询和加载相应的字型码,以确保每个汉字都能被准确无误地显示出来。 ### 技术人员的使用场景 技术人员在开发过程中,可能会遇到需要在有限的显示屏上显示中文的...

    汉字ASCII码表

    从部分示例中可以看出,该“汉字ASCII码表”实际上是将一些Unicode编码映射到类似ASCII码的格式上,以便于理解和处理。这种做法虽然在一定程度上方便了编码转换和数据处理,但并不符合标准的Unicode或ASCII规范。...

    手机扫码二维码(模仿微信).rar

    总的来说,开发一个手机扫码二维码的功能,需要掌握图像处理技术、熟悉Android或iOS开发环境、理解权限管理和用户交互设计,同时具备一定的性能优化和测试能力。这个项目可以作为学习移动开发和实践二维码应用的绝佳...

    易语言汉字和ASCII码之间的转换

    在中文环境中,汉字编码通常涉及到多种标准,如GBK、GB2312、UTF-8等,而ASCII码则主要用于表示英文字符。易语言作为一款中国本土的编程语言,提供了解决汉字与ASCII码之间转换的功能。本节将详细探讨易语言中的汉字...

    oidProducer铺码软件中文版

    "oidProducer铺码软件中文版"是一款专为点读笔书籍设计的铺码工具,它主要功能是生成和管理OID(Object Identifier)码,这些码是点读笔识别书籍内容的关键。OIDProducer作为中文版软件,更加便于国内用户理解和操作...

    完整汉字笔画笔顺Unicode和GB码数据库(20902汉字)

    在计算机系统中,GB码通常用于存储和传输汉字,尤其是在中文操作系统和软件中。 这个数据库包含的不仅是汉字的Unicode和GB码,还包含了汉字的笔画和笔顺信息。这些数据对于汉字输入法的研发、汉字识别技术的进步、...

    手机号码交易网手机选号网站源码

    标题中的“手机号码交易网手机选号网站源码”指的是一个用于在线交易手机号码的网站系统,其核心是源代码,使用的是ASP编程语言和Access数据库。这种网站源码为开发者提供了一个基础平台,用于搭建自己的手机号码...

    THC-NOKIA-UNLOCK手机锁码恢复

    首先,我们需要理解什么是手机锁码。手机锁码通常指的是PIN码,是Personal Identification Number的缩写,它是手机的一种安全机制,防止未经授权的人员使用。当手机开机或从待机模式唤醒时,用户需要输入正确的PIN码...

    汉字区位码对照表

    通过对汉字区位码的学习和了解,我们可以更好地理解汉字编码的原理和技术背景,这对于从事中文信息处理工作的技术人员来说是非常重要的基础。 以上内容详细介绍了汉字区位码的相关知识,包括其概念、编码规则、查找...

    汉字区位码速查工具[中文免费版]

    汉字区位码速查工具是一款专为中文用户设计的实用软件,主要功能是帮助用户快速查找和理解汉字的区位码。区位码是汉字在计算机内存储和处理时使用的一种编码方式,由两个十六进制数字组成,分别代表汉字在对应区和位...

    汉字拼音及首字母unicode码对照库(2万多条)

    3. **汉字与Unicode码转换**:在跨平台的数据交换中,将汉字转换成Unicode码,可以避免因编码问题导致的乱码问题。 4. **自然语言处理**:在进行中文自然语言处理任务,如词性标注、语义理解时,拼音信息可以帮助...

    电话号码及日期时间提取(正则表达式 C)

    在简体中文网页中,日期通常会用汉字表示月份和日期,比如“2022年5月20日”,时间则可能是24小时制。正则表达式需要灵活应对这些变化,例如: - 简体中文日期正则:`\d{4}年\d{1,2}月\d{1,2}日` - 24小时制时间...

    ASII码制对应表

    ASCII码,全称为美国标准信息交换代码(American Standard Code for Information Interchange)...掌握ASCII码可以帮助我们更好地理解计算机如何存储和处理文本信息,同时也有助于解决跨平台或跨系统的文本兼容性问题。

    中国联通H码汇总表-2019

    首先,H码,全称“Handover Code”,中文可以理解为“切换码”或“转接码”。在通信网络中,当用户在不同区域间移动时,为了保持通话的连续性,手机需要在不同的基站之间进行切换。H码就是在这个过程中起到关键作用...

    数字电路不挂科-1-数制与码制_数字电路不挂科-1-数制与码制_

    在学习数字电路的过程中,理解并掌握数制与码制是至关重要的第一步。数制是表示数字的方式,而码制则是在特定应用场景中对数字进行编码的规则。以下是对"数字电路不挂科-1-数制与码制"这一主题的详细解释。 首先,...

Global site tag (gtag.js) - Google Analytics