論壇上許多的帖子都是在討論手機上的中文碼制標題,我也曾經被此類的標題所困擾,並且得到了不少熱情的朋友的幫助。通過一端時間的材料查找和測試學習,我對這個標題有一點點自己的懂得和想法,不敢敝帚自珍,特分享給大家,由於本人程度有限,況且也是業余的開發愛好者,沒有專業的理論學習程度,所以請大家就文章中的一些錯誤予以體諒並提出批評,本篇的文章僅做拋磚引玉,非常的歡迎大家的跟貼,我們群策群力,共同來解決這個標題。:)
論壇上許多的帖子都是在討論手機上的中文碼制標題,我也曾經被此類的標題所困擾,並且得到了不少熱情的朋友的幫助。通過一端時間的材料查找和測試學習,我對這個標題有一點點自己的懂得和想法,不敢敝帚自珍,特分享給大家,由於本人程度有限,況且也是業余的開發愛好者,沒有專業的理論學習程度,所以請大家就文章中的一些錯誤予以體諒並提出批評,本篇的文章僅做拋磚引玉,非常的歡迎大家的跟貼,我們群策群力,共同來解決這個標題。:)
手機裡面的字符串基礎上都是采用的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 writeShortmethod giving the number of bytes to follow. This value is the numberof bytes actually written out, not the length of the string. Followingthe length, each character of the string is output, in sequence, usingthe UTF-8 encoding for the character.If no exception is thrown, thecounter written is incremented by the total number of bytes written tothe 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系列),那真的沒有措施了,只有等候他的中文版本出來了 呵呵,:)我的信箱是 [email protected],非常的歡迎大家來信共同討論這個標題,也非常的希看交到技巧上的朋友.
共同努力,一起提高!