Discussion Board

Page 1 of 3 123 LastLast
Results 1 to 15 of 32
  1. #1
    Regular Contributor zhaofei8009's Avatar
    Join Date
    Aug 2003
    Location
    China Shanghai
    Posts
    240
    论坛上很多的帖子都是在讨论手机上的中文码制问题,我也曾綺被此类的问题所困扰,并且得到了不少热心的朋友的帮助。通过一端时间的资料查找和测试学习,我对这个问题有一点点自己的理解和想法,不敢敝帚自珍,特分享给大家,由于本人水平有限,况且也是业余的开发爱好者,没有专业的理论学习水平,所以请大家就文章中的一些错误予以谅解并提出批评,本篇的文章仅做抛砖引玉,非常的欢觃大家的跟贴,我们群策群力,共同来解决这个问题。

    手机里面的字符串基本上都是采用的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字符也使用两个字节来表示而不是一个字节


    zhaofei8009

  2. #2
    Regular Contributor zhaofei8009's Avatar
    Join Date
    Aug 2003
    Location
    China Shanghai
    Posts
    240
    当然英文字符串在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,这个类也可用于文本文件操作。

    /**
    * <p>Title: </p>
    * <p>Description: unicode字串转换工具</p>
    * <p>Copyright: Copyright (c) 2003</p>
    * <p>Company: CC Studio</p>
    * @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方法取得。我们也可以转化成相关的支持的编码机制来实际的运行我们的程序。
    这种方式我们通常会用在有关手机中文问题传输中,因为在联网时的手机是不确定的。以下我给出一段实例代码,和大家探讨一下这个问题。

    zhaofei8009

  3. #3
    Regular Contributor zhaofei8009's Avatar
    Join Date
    Aug 2003
    Location
    China Shanghai
    Posts
    240
    服务器到客户端:
    ------------------------------------------------------------------
    下面代码是服务器端把字符写到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,非常的欢觃大家来信共同讨论这个问题,也非常的希望交到技术上的朋友.

    共同努力,一起进步!

    zhaofei8009

  4. #4
    Registered User frius's Avatar
    Join Date
    Jun 2003
    Posts
    6
    好贴,收藏,先!

  5. #5
    Regular Contributor godener's Avatar
    Join Date
    Nov 2003
    Location
    Fuzhou china
    Posts
    131
    顶! 感谢zhaofei的奉献精神!

  6. #6
    Regular Contributor zhaofei8009's Avatar
    Join Date
    Aug 2003
    Location
    China Shanghai
    Posts
    240
    不用谢,我仅做抛砖引玉,希望大家能跟贴,共同讨论这个话题,解决掉这个问题

    共同努力,一起进步!


    zhaofei8009

  7. #7
    Registered User rosezhang's Avatar
    Join Date
    Jan 2004
    Posts
    11
    Thank you for you detailed help on Chinese. However, I am still a little confused. I have problems to let manifest/jad file show Chinese.

    I tried to put unicode, escaped unicode, native Chinese written from a Chinese OS into manifest/jad file, but they did not work. Now, I saw your instructions for put UTF-8 code, I tried, I could not make it work either. I think I must have done something wrong.

    I want to show
    MIDlet-Name: 空战

    I put into manifest/jad:
    MIDlet-Name: E7A9BAE68898

    When I download the game from my Chinese handset, it still shows the samething: E7A9BAE68898, not 空战

    Can you tell me what went wrong?
    Thanks a lot!

  8. #8
    Registered User rosezhang's Avatar
    Join Date
    Jan 2004
    Posts
    11
    I put ^@^ in, it still not work.

    Would you please put a simple jad or manifest with Chinese in UTF in. It would help a lot!!!

    Thanks In Advance!!!

  9. #9
    Regular Contributor zhaofei8009's Avatar
    Join Date
    Aug 2003
    Location
    China Shanghai
    Posts
    240
    rosezhang兄,请试用一下这个工具好么Sun ONE studio 4 Update 1,Mobile Edition
    他支持你在Jad/manifest编糭中输入中文,并且帮助你转化成UTF8的码制
    这样手机就可以识别中文的手机名称不出问题了

    共同努力, 一起进步!

    zhaofei8009

  10. #10
    Registered User iso9660's Avatar
    Join Date
    Apr 2003
    Location
    shanghai
    Posts
    44
    jad的中文显示是一个比较搞人的问题,可也是疑问比较少的,因为我们如果用jbuilder这些工具是不会有这个问题的,可是这样的解决方法不是本质上的。

    实际上,只要把jad文件保存为UTF8的文件格式,那么里面的中文文件名就可以被正确显示,利用windows里面带的写字板或者ultraedit里面的转换功能就可以完成。

    这个问题的本质是:jad里面的Name如果是UTF8编码的话,手机就能正确显示,而把文件存为UTF8是最简单的办法,因为E文在UTF8里面是不变的,中文却会被正确编码。

    I put into manifest/jad:
    MIDlet-Name: E7A9BAE68898
    这种转换方法是对UTF8编码的一个误解。UTF8在内码层面是个二进制的串,绝不是一个可以这样显示的字符串。

    如果使用ant工具打包的话,会有一些特别的问题,这个就不在这里详细展开了。

  11. #11
    Regular Contributor zhengwei's Avatar
    Join Date
    Mar 2003
    Location
    Beijing
    Posts
    98
    Hi all,

    This is a very good discussion on Chinese development issues.

    Another related issue is how to pass Chinese XML data between a MIDP and server side applications. For example, a MIDP gets Chinese data in XML from a servlet and displays the data in UI or a MIDP posts Chinese data to a servlet and the servlet stores the data into a database table. Can anyone share his/her experience here?

    br
    zw

  12. #12
    Registered User dearland's Avatar
    Join Date
    Aug 2003
    Posts
    4
    谢谢 :-)

  13. #13
    Regular Contributor zsj2003's Avatar
    Join Date
    Apr 2003
    Location
    china
    Posts
    181
    好文章!
    谢谢

    zsj2003

  14. #14
    Registered User lxczyllxc0003's Avatar
    Join Date
    Feb 2004
    Posts
    36
    大家说来说去,总是没有设计到关于HTTP-GET,在MIDLET与SERVLET通讯时的中文传输问题,我在使用时,当使用HTTP-POST方法传一些中文值时,能从流中解析出来交显示,但当用GET方法传过来的中文在7210模拟器上却总是读到乱码,不知应怎么转换?
    通过system.getproperty可知7210的默认编码为ISO-8859-1,我SERVLET响应时设置类型为CONTENT_TYPE = "text/html; charset=UTF-8";并加入 response.addHeader("region","北京");但从MIDLET中解析出来总是乱码,请大家帮忙分析一下是什么訽因。

  15. #15
    Registered User iso9660's Avatar
    Join Date
    Apr 2003
    Location
    shanghai
    Posts
    44
    回楼上的
    实务操作的时候,中文涉及的领域很多
    使用 servlet的时候,你的操作系统是什么?
    比如redhat + apache ,那么首先编译java程序的时候就要注意加
    encoding=GB2312
    同时,apache的输出编码,目前的移动网关下,必须设置为 ISO-8859-1

    在中文windows平台下,又是另一种情况。

Page 1 of 3 123 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Nokia Developer aims to help you create apps and publish them so you can connect with users around the world.

京ICP备05048969号  © Copyright Nokia 2013 All rights reserved