java对字符串编码转换_(转) Java字符编码转换
JVM
JVM啟動(dòng)后,JVM會(huì)設(shè)置一些系統(tǒng)屬性以表明JVM的缺省區(qū)域。
user.language,user.region,file.encoding等。
可以使用System.getProperties()詳細(xì)查看所有的系統(tǒng)屬性。
如在英文操作系統(tǒng)(如UNIX)下,可以使用如下屬性定義強(qiáng)制指定JVM為中文環(huán)境
-Dclient.encoding.override=GBK -
Dfile.encoding=GBK -Duser.language=zh -Duser.region=CN
.java-->.class編譯
說(shuō)明:一般javac根據(jù)當(dāng)前os區(qū)域設(shè)置,自動(dòng)決定源文件的編碼.可以通過(guò)-encoding強(qiáng)制指定.
錯(cuò)誤可能:
1 gbk編碼源文件在英文環(huán)境下編譯,javac不能正確轉(zhuǎn)換.曾見(jiàn)于java/jsp在英文unix下.
檢測(cè)方法:寫\u4e00格式的漢字,繞
開javac編碼,再在jvm中,將漢字作為int打印,看值是否相等;或直接以UTF-8編碼打開.class
文件,看看常量字符串是否正
確保存漢字。
文件讀寫
外部數(shù)據(jù)如文件經(jīng)過(guò)讀寫和轉(zhuǎn)換兩個(gè)步驟,轉(zhuǎn)為jvm所使用字符。InputStream/OutputStream用于讀寫原始外部數(shù)據(jù),
Reader/Writer執(zhí)行讀寫和轉(zhuǎn)換兩個(gè)步驟。
1 文件讀寫轉(zhuǎn)換由java.io.Reader/Writer執(zhí)行;輸入輸出流 InputStream/OutputStream
處理漢字不合適,應(yīng)該首選使用
Reader/Writer,如 FileReader/FileWriter。
2
FileReader/FileWriter使用JVM當(dāng)前編碼讀寫文件.如果有其它編碼格式,使用InputStreamReader/OutputStreamWriter
3 PrintStream有點(diǎn)特殊,它自動(dòng)使用jvm缺省編碼進(jìn)行轉(zhuǎn)換。
讀取.properties文件
.propeties 文件由Properties類以iso8859-1編碼讀取,因此不能在其中直接寫漢字,需要使用JDK
的native2ascii工具轉(zhuǎn)換
漢字為\uXXXX格式。命令行:native2ascii ?encoding GBK inputfile
outputfile
讀取XML文件
1 XML文件讀寫同于文件讀寫,但應(yīng)注意確保XML頭中聲明如 xml version=”1.0”
encoding=”gb2312” ?>與文件編碼保
持一致。
2
javax.xml.SAXParser類接受InputStream作為輸入?yún)?shù),對(duì)于Reader,需要用org.xml.sax.InputSource包裝一下,再給
SAXParser。
3 對(duì)于UTF-8編碼 XML,注意防止編輯器自動(dòng)加上\uFFFE BOM頭, xml parser會(huì)報(bào)告content is not
allowed in prolog。
字節(jié)數(shù)組
1 使用 new String(byteArray,encoding) 和 String.getBytes(encoding)
在字節(jié)數(shù)組和字符串之間進(jìn)行轉(zhuǎn)換
也可以用ByteArrayInputStream/ByteArrayOutputStream轉(zhuǎn)為流后再用InputStreamReader/OutputStreamWriter轉(zhuǎn)換。
錯(cuò)誤編碼的字符串(iso8859-1轉(zhuǎn)碼gbk)
如果我們得到的字符串是由錯(cuò)誤的轉(zhuǎn)碼方式產(chǎn)生的,例如:對(duì)于gbk中文,由iso8859-1方式轉(zhuǎn)換,此時(shí)如果用調(diào)試器看到的字
符串一般是 的樣子,長(zhǎng)度一般為文本的字節(jié)長(zhǎng)度,而非漢字個(gè)數(shù)。
可以采用如下方式轉(zhuǎn)為正確的中文:
text = new String( text.getBytes(“iso8859-1”),”gbk”);
WEB/Servlet/JSP
1 對(duì)于JSP,確定頭部加上
contentType="text/html;charset=gb2312"%>這樣的標(biāo)簽。
2 對(duì)于Servlet,確定 設(shè)置setContentType (“text/html;
charset=gb2312”),以上兩條用于使得輸出漢字沒(méi)有問(wèn)題。
3 為輸出HTML head中加一個(gè)
content="text/html; charset=gb2312"> ,讓瀏覽器正確
確定HTML編碼。
4
為Web應(yīng)用加一個(gè)Filter,確保每個(gè)Request明確調(diào)用setCharacterEncoding方法,讓輸入漢字能夠正確解析。
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServletRequest;
public class SetCharacterEncodingFilter
implements Filter {
public SetCharacterEncodingFilter()
{}
protected boolean debug = false;
protected String encoding = null;
protected FilterConfig filterConfig = null;
public void destroy() {
this.encoding = null;
this.filterConfig = null;
}
public void doFilter(ServletRequest request, ServletResponse
response,
FilterChain chain) throws IOException, ServletException {
// if (request.getCharacterEncoding() == null)
// {
// String encoding = getEncoding();
// if (encoding != null)
// request.setCharacterEncoding(encoding);
//
// }
request.setCharacterEncoding(encoding);
if ( debug ){
System.out.println(
((HttpServletRequest)request).getRequestURI()+"setted to "+encoding
);
}
chain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException
{
this.filterConfig = filterConfig;
this.encoding = filterConfig.getInitParameter("encoding");
this.debug = "true".equalsIgnoreCase(
filterConfig.getInitParameter("debug") );
}
protected String getEncoding() {
return (this.encoding);
}
}
web.xml中加入:
LocalEncodingFilter
LocalEncodingFilter
com.ccb.ectipmanager.request.SetCharacterEncodingFilter
encoding
gb2312
debug
false
LocalEncodingFilter
JNIEXPORT jstring
NewStringPlatform(JNIEnv *env, const char *str);
JNIEXPORT const char *
GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean
*isCopy);
JNIEXPORT jstring JNICALL
JNU_NewStringPlatform(JNIEnv *env, const char *str);
JNIEXPORT const char * JNICALL
JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean
*isCopy);
JNIEXPORT void JNICALL
JNU_ReleaseStringPlatformChars(JNIEnv *env, jstring jstr, const
char *str);
附件jni_util.h,jni_util.c
JDK1.4/1.5新增部分
字符集相關(guān)類(Charset/CharsetEncoder/CharsetDecoder)
jdk1.4開始,對(duì)字符集的支持在java.nio.charset包中實(shí)現(xiàn)。
常用功能:
1 列出jvm所支持字符集:Charset.availableCharsets()
2 能否對(duì)看某個(gè)Unicode字符編碼,CharsetEncoder.canEncode()
常見(jiàn)問(wèn)題
在JVM下,用System.out.println不能正確打印中文,顯示為???
System.out.println是PrintStream,它采用jvm缺省字符集進(jìn)行轉(zhuǎn)碼工作,如果jvm的缺省字符集為iso8859-1,則中文顯示會(huì)
有問(wèn)題。此問(wèn)題常見(jiàn)于Unix下,jvm的區(qū)域沒(méi)有明確指定的情況。
在英文UNIX環(huán)境下,用System.out.println能夠正確打印漢字,但是內(nèi)部處理錯(cuò)誤
可能是漢字在輸入轉(zhuǎn)換時(shí),就沒(méi)有正確轉(zhuǎn)碼:
即gbk文本à(iso8859-1轉(zhuǎn)碼)àjvm char(iso8859-1編碼漢字)à
(iso8859-1轉(zhuǎn)碼)à輸出。
gbk漢字經(jīng)過(guò)兩次錯(cuò)誤轉(zhuǎn)碼,原封不動(dòng)的被傳遞到輸出,但是在jvm中,并未以正確的unicode編碼表示,而是以一個(gè)漢字字節(jié)
一個(gè)char的方式表示,從而導(dǎo)致此類錯(cuò)誤。
GB2312-80,GBK,GB18030-2000 漢字字符集
GB2312-80 是在國(guó)內(nèi)計(jì)算機(jī)漢字信息技術(shù)發(fā)展初始階段制定的,其中包含了大部分常用的一、二級(jí)漢字,和 9 區(qū)的符號(hào)。該
字符集是幾乎所有的中文系統(tǒng)和國(guó)際化的軟件都支持的中文字符集,這也是最基本的中文字符集。其編碼范圍是高位0xa1-
0xfe,低位也是 0xa1-0xfe;漢字從 0xb0a1 開始,結(jié)束于 0xf7fe;
GBK 是 GB2312-80 的擴(kuò)展,是向上兼容的。它包含了 20902 個(gè)漢字,其編碼范圍是 0x8140-0xfefe,剔除高位
0x80 的字位
。其所有字符都可以一對(duì)一映射到 Unicode 2.0,也就是說(shuō) JAVA 實(shí)際上提供了 GBK 字符集的支持。這是現(xiàn)階段
Windows 和
其它一些中文操作系統(tǒng)的缺省字符集,但并不是所有的國(guó)際化軟件都支持該字符集,感覺(jué)是他們并不完全知道 GBK 是怎么回
事。值得注意的是它不是國(guó)家標(biāo)準(zhǔn),而只是規(guī)范。隨著
GB18030-2000國(guó)標(biāo)的發(fā)布,它將在不久的將來(lái)完成它的歷史使命。
GB18030-2000(GBK2K) 在 GBK 的基礎(chǔ)上進(jìn)一步擴(kuò)展了漢字,增加了藏、蒙等少數(shù)民族的字形。GBK2K
從根本上解決了字位不
夠,字形不足的問(wèn)題。它有幾個(gè)特點(diǎn),
它并沒(méi)有確定所有的字形,只是規(guī)定了編碼范圍,留待以后擴(kuò)充。
編碼是變長(zhǎng)的,其二字節(jié)部分與 GBK 兼容;四字節(jié)部分是擴(kuò)充的字形、字位,其編碼范圍是首字節(jié)
0x81-0xfe、二字節(jié)0x30
-0x39、三字節(jié) 0x81-0xfe、四字節(jié)0x30-0x39。
UTF-8/UTF-16/UTF-32
UTF,即Unicode Transformer Format,是Unicode代碼點(diǎn)(code
point)的實(shí)際表示方式,按其基本長(zhǎng)度所用位數(shù)分為UTF-
8/16/32。它也可以認(rèn)為是一種特殊的外部數(shù)據(jù)編碼,但能夠與Unicode代碼點(diǎn)做一一對(duì)應(yīng)。
UTF-8是變長(zhǎng)編碼,每個(gè)Unicode代碼點(diǎn)按照不同范圍,可以有1-3字節(jié)的不同長(zhǎng)度。
UTF-16長(zhǎng)度相對(duì)固定,只要不處理大于\U200000范圍的字符,每個(gè)Unicode代碼點(diǎn)使用16位即2字節(jié)表示,超出部分使用兩個(gè)
UTF-16即4字節(jié)表示。按照高低位字節(jié)順序,又分為UTF-16BE/UTF-16LE。
UTF-32長(zhǎng)度始終固定,每個(gè)Unicode代碼點(diǎn)使用32位即4字節(jié)表示。按照高低位字節(jié)順序,又分為UTF-32BE/UTF-32LE。
UTF 編碼有個(gè)優(yōu)點(diǎn),即盡管編碼字節(jié)數(shù)不等,但是不像gb2312/gbk編碼一樣,需要從文本開始尋找,才能正確對(duì)漢字進(jìn)行定位
。在UTF編碼下,根據(jù)相對(duì)固 定的算法,從當(dāng)前位置就能夠知道當(dāng)前字節(jié)是否是一個(gè)代碼點(diǎn)的開始還是結(jié)束,從而相對(duì)簡(jiǎn)單的
進(jìn)行字符定位。不過(guò)定位問(wèn)題最簡(jiǎn)單的還是UTF-32,它根本不 需要進(jìn)行字符定位,但是相對(duì)的大小也增加不少。
關(guān)于GCJ JVM
GCJ并未完全依照sun jdk的做法,對(duì)于區(qū)域和編碼問(wèn)題考慮尚不夠周全。GCJ啟動(dòng)時(shí),區(qū)域始終設(shè)為en_US,編碼也缺省為
iso8859-1。但是可以用Reader/Writer做正確編碼轉(zhuǎn)換
總結(jié)
以上是生活随笔為你收集整理的java对字符串编码转换_(转) Java字符编码转换的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: SSIS数据转换器及字符转换器使用
- 下一篇: 如何搜索视频和字幕?