`
r2100
  • 浏览: 29801 次
  • 来自: ...
社区版块
存档分类
最新评论

JAVA字符集和字符串的编码

阅读更多
先提出问题:

都知道,windows XP 的默认编码方式是GBK,

验证如下:

Charset defaultCharset=java.nio.charset.Charset.defaultCharset();

String name=defaultCharset.name();//输入GBK

也可以从另一个编码的角度来验证:

String testStr = "中国";

byte[] bytes = testStr.getBytes(); //[-42, -48, -71, -6]

byte[] gbkbytes = testStr.getBytes("GBK"); //[-42, -48, -71, -6]

是相同的!

这样,问题就来了,如果我想对字符进行UTF-8格式的编码,怎么做?

下面就讨论这个问题。

JDK本身没有提供对字符串进行编码的接口,所有编码相关的类都位于sun.io.*;和java.nio.charset;中.


其实,有一个私有类被隐藏在JDK中,那就是下面要介绍的对String进行编码、解码的工具类:


java.lang.StringCoding;


它是一个内部类,所有的方法都是默认访问的,一位着只有在lang包中的程序才可见它。


直接把这个类复制来,然后把构造访问值改为public (该类的源码附后)


比如要对一个字符串,进行UTF-8编码

String testStr = "中国";


//转换为char数组

char[] defaultChars = {‘中’,‘国’};


//用UTF-8进行编码(encode)

byte[] utfbytes = StringCoding.encode("UTF-8", defaultChars, 0, defaultChars.length);

//用UTF-8进行解码(decode)

char[] utfChars=StringCoding.decode("UTF-8", utfbytes, 0,utfbytes.length);


//将转换编码后的字符串打印出来

String utfStr=Arrays.toString(utfChars);



附源文件 StringCoding:


/*

* @(#)StringCoding.java 1.13 03/12/19

*

* Copyright 2004 Sun Microsystems, Inc. All rights reserved.

* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.

*/


package java.lang;


import java.io.CharConversionException;

import java.io.UnsupportedEncodingException;

import java.lang.ref.SoftReference;

import java.nio.ByteBuffer;

import java.nio.CharBuffer;

import java.nio.BufferOverflowException;

import java.nio.BufferUnderflowException;

import java.nio.charset.Charset;

import java.nio.charset.CharsetDecoder;

import java.nio.charset.CharsetEncoder;

import java.nio.charset.CharacterCodingException;

import java.nio.charset.CoderResult;

import java.nio.charset.CodingErrorAction;

import java.nio.charset.IllegalCharsetNameException;

import java.nio.charset.MalformedInputException;

import java.nio.charset.UnsupportedCharsetException;

import sun.io.ByteToCharConverter;

import sun.io.CharToByteConverter;

import sun.io.Converters;

import sun.misc.MessageUtils;

import sun.nio.cs.HistoricallyNamedCharset;



/**

* Utility class for string encoding and decoding.

*/


class StringCoding {


private StringCoding() { }


/* The cached coders for each thread

*/

private static ThreadLocal decoder = new ThreadLocal();

private static ThreadLocal encoder = new ThreadLocal();


private static boolean warnUnsupportedCharset = true;


private static Object deref(ThreadLocal tl) {

SoftReference sr = (SoftReference)tl.get();

if (sr == null)

return null;

return sr.get();

}


private static void set(ThreadLocal tl, Object ob) {

tl.set(new SoftReference(ob));

}


// Trim the given byte array to the given length

//

private static byte[] trim(byte[] ba, int len) {

if (len == ba.length)

return ba;

byte[] tba = new byte[len];

System.arraycopy(ba, 0, tba, 0, len);

return tba;

}


// Trim the given char array to the given length

//

private static char[] trim(char[] ca, int len) {

if (len == ca.length)

return ca;

char[] tca = new char[len];

System.arraycopy(ca, 0, tca, 0, len);

return tca;

}


private static Charset lookupCharset(String csn) {

if (Charset.isSupported(csn)) {

try {

return Charset.forName(csn);

} catch (UnsupportedCharsetException x) {

throw new Error(x);

}

}

return null;

}


private static void warnUnsupportedCharset(String csn) {

if (warnUnsupportedCharset) {

// Use sun.misc.MessageUtils rather than the Logging API or

// System.err since this method may be called during VM

// initialization before either is available.

MessageUtils.err("WARNING: Default charset " + csn +

" not supported, using ISO-8859-1 instead");

warnUnsupportedCharset = false;

}

}



// -- Decoding --


// Encapsulates either a ByteToCharConverter or a CharsetDecoder

//

private static abstract class StringDecoder {

private final String requestedCharsetName;

protected StringDecoder(String requestedCharsetName) {

this.requestedCharsetName = requestedCharsetName;

}

final String requestedCharsetName() {

return requestedCharsetName;

}

abstract String charsetName();

abstract char[] decode(byte[] ba, int off, int len);

}


// A string decoder based upon a ByteToCharConverter

//

private static class ConverterSD

extends StringDecoder

{

private ByteToCharConverter btc;


private ConverterSD(ByteToCharConverter btc, String rcn) {

super(rcn);

this.btc = btc;

}


String charsetName() {

return btc.getCharacterEncoding();

}


char[] decode(byte[] ba, int off, int len) {

int en = btc.getMaxCharsPerByte() * len;

char[] ca = new char[en];

if (len == 0)

return ca;

btc.reset();

int n = 0;

try {

n = btc.convert(ba, off, off + len, ca, 0, en);

n += btc.flush(ca, btc.nextCharIndex(), en);

} catch (CharConversionException x) {

// Yes, this is what we've always done

n = btc.nextCharIndex();

}

return trim(ca, n);

}


}


// A string decoder based upon a CharsetDecoder

//

private static class CharsetSD

extends StringDecoder

{

private final Charset cs;

private final CharsetDecoder cd;


private CharsetSD(Charset cs, String rcn) {

super(rcn);

this.cs = cs;

this.cd = cs.newDecoder()

.onMalformedInput(CodingErrorAction.REPLACE)

.onUnmappableCharacter(CodingErrorAction.REPLACE);

}


String charsetName() {

if (cs instanceof HistoricallyNamedCharset)

return ((HistoricallyNamedCharset)cs).historicalName();

return cs.name();

}


char[] decode(byte[] ba, int off, int len) {

int en = (int)(cd.maxCharsPerByte() * len);

char[] ca = new char[en];

if (len == 0)

return ca;

cd.reset();

ByteBuffer bb = ByteBuffer.wrap(ba, off, len);

CharBuffer cb = CharBuffer.wrap(ca);

try {

CoderResult cr = cd.decode(bb, cb, true);

if (!cr.isUnderflow())

cr.throwException();

cr = cd.flush(cb);

if (!cr.isUnderflow())

cr.throwException();

} catch (CharacterCodingException x) {

// Substitution is always enabled,

// so this shouldn't happen

throw new Error(x);

}

return trim(ca, cb.position());

}


}


static char[] decode(String charsetName, byte[] ba, int off, int len)

throws UnsupportedEncodingException

{

StringDecoder sd = (StringDecoder)deref(decoder);

String csn = (charsetName == null) ? "ISO-8859-1" : charsetName;

if ((sd == null) || !(csn.equals(sd.requestedCharsetName())

|| csn.equals(sd.charsetName()))) {

sd = null;

try {

Charset cs = lookupCharset(csn);

if (cs != null)

sd = new CharsetSD(cs, csn);

else

sd = null;

} catch (IllegalCharsetNameException x) {

// FALL THROUGH to ByteToCharConverter, for compatibility

}

if (sd == null)

sd = new ConverterSD(ByteToCharConverter.getConverter(csn),

csn);

set(decoder, sd);

}

return sd.decode(ba, off, len);

}


static char[] decode(byte[] ba, int off, int len) {

String csn = Converters.getDefaultEncodingName();

try {

return decode(csn, ba, off, len);

} catch (UnsupportedEncodingException x) {

Converters.resetDefaultEncodingName();

warnUnsupportedCharset(csn);

}

try {

return decode("ISO-8859-1", ba, off, len);

} catch (UnsupportedEncodingException x) {

// If this code is hit during VM initialization, MessageUtils is

// the only way we will be able to get any kind of error message.

MessageUtils.err("ISO-8859-1 charset not available: "

+ x.toString());

// If we can not find ISO-8859-1 (a required encoding) then things

// are seriously wrong with the installation.

System.exit(1);

return null;

}

}




// -- Encoding --


// Encapsulates either a CharToByteConverter or a CharsetEncoder

//

private static abstract class StringEncoder {

private final String requestedCharsetName;

protected StringEncoder(String requestedCharsetName) {

this.requestedCharsetName = requestedCharsetName;

}

final String requestedCharsetName() {

return requestedCharsetName;

}

abstract String charsetName();

abstract byte[] encode(char[] cs, int off, int len);

}


// A string encoder based upon a CharToByteConverter

//

private static class ConverterSE

extends StringEncoder

{

private CharToByteConverter ctb;


private ConverterSE(CharToByteConverter ctb, String rcn) {

super(rcn);

this.ctb = ctb;

}


String charsetName() {

return ctb.getCharacterEncoding();

}


byte[] encode(char[] ca, int off, int len) {

int en = ctb.getMaxBytesPerChar() * len;

byte[] ba = new byte[en];

if (len == 0)

return ba;


ctb.reset();

int n;

try {

n = ctb.convertAny(ca, off, (off + len),

ba, 0, en);

n += ctb.flushAny(ba, ctb.nextByteIndex(), en);

} catch (CharConversionException x) {

throw new Error("Converter malfunction: " +

ctb.getClass().getName(),

x);

}

return trim(ba, n);

}


}


// A string encoder based upon a CharsetEncoder

//

private static class CharsetSE

extends StringEncoder

{

private Charset cs;

private CharsetEncoder ce;


private CharsetSE(Charset cs, String rcn) {

super(rcn);

this.cs = cs;

this.ce = cs.newEncoder()

.onMalformedInput(CodingErrorAction.REPLACE)

.onUnmappableCharacter(CodingErrorAction.REPLACE);

}


String charsetName() {

if (cs instanceof HistoricallyNamedCharset)

return ((HistoricallyNamedCharset)cs).historicalName();

return cs.name();

}


byte[] encode(char[] ca, int off, int len) {

int en = (int)(ce.maxBytesPerChar() * len);

byte[] ba = new byte[en];

if (len == 0)

return ba;


ce.reset();

ByteBuffer bb = ByteBuffer.wrap(ba);

CharBuffer cb = CharBuffer.wrap(ca, off, len);

try {

CoderResult cr = ce.encode(cb, bb, true);

if (!cr.isUnderflow())

cr.throwException();

cr = ce.flush(bb);

if (!cr.isUnderflow())

cr.throwException();

} catch (CharacterCodingException x) {

// Substitution is always enabled,

// so this shouldn't happen

throw new Error(x);

}

return trim(ba, bb.position());

}


}


static byte[] encode(String charsetName, char[] ca, int off, int len)

throws UnsupportedEncodingException

{

StringEncoder se = (StringEncoder)deref(encoder);

String csn = (charsetName == null) ? "ISO-8859-1" : charsetName;

if ((se == null) || !(csn.equals(se.requestedCharsetName())

|| csn.equals(se.charsetName()))) {

se = null;

try {

Charset cs = lookupCharset(csn);

if (cs != null)

se = new CharsetSE(cs, csn);

} catch (IllegalCharsetNameException x) {

// FALL THROUGH to CharToByteConverter, for compatibility

}

if (se == null)

se = new ConverterSE(CharToByteConverter.getConverter(csn),

csn);

set(encoder, se);

}

return se.encode(ca, off, len);

}


static byte[] encode(char[] ca, int off, int len) {

String csn = Converters.getDefaultEncodingName();

try {

return encode(csn, ca, off, len);

} catch (UnsupportedEncodingException x) {

Converters.resetDefaultEncodingName();

warnUnsupportedCharset(csn);

}

try {

return encode("ISO-8859-1", ca, off, len);

} catch (UnsupportedEncodingException x) {

// If this code is hit during VM initialization, MessageUtils is

// the only way we will be able to get any kind of error message.

MessageUtils.err("ISO-8859-1 charset not available: "

+ x.toString());

// If we can not find ISO-8859-1 (a required encoding) then things

// are seriously wrong with the installation.

System.exit(1);

return null;

}

}


}
分享到:
评论

相关推荐

    Java 所有字符串转UTF-8 万能工具类-GetEncode.java

    不需要关心接受的字符串编码是UTF_8还是GBK,还是ios-8859-1,自动转换为utf-8编码格式,无需判断字符串原有编码,用法://处理编码String newStr = GetEncode.transcode(oldStr);

    JAVA字符串操作类CTool.java字符转换类.rar

    字符串从GBK编码转换为Unicode编码、对字符串进行md5加密、sql语句 处理、把null转换为字符串"0"、null 处理、long型变量转换成String型变量、int型变量转换成String型变量、String型变量转换成int型变量、把null值...

    java字符串验证工具

    String 字符串操作工具类,sql防注入方法 过滤通过页面表单提交的字符 用特殊的字符连接字符串 将字符串数组转换为逗号链接的字符串,并且去掉最后一个逗号 分割字符串 字符串字符集转换 编码转换方法 将html文档...

    如何使用Java代码获取文件、文件流或字符串的编码方式.zip

    本工程用于研究如何使用Java代码获取文件、文件流或字符串的编码方式 本工程编码方式:UTF-8 开发工具:MyEclipse 参考博客:http://blog.csdn.net/gaohuanjie/article/details/43735891

    众多字符集编码的区别Unicode向GB2312转换方法说明及示例

    众多字符集编码的区别Unicode向GB2312转换方法说明及包括ASCII码部分及GB2312字符集。 ASCII码部分为128个字符,GB2312字符集为7445个字符。 ASCII码部分不需要用映射表。 GB2312 table可分为4段,每段都是连续的。...

    Java CTool.java一个好用的字符串操作类.rar

    这个类的功能可实现将数据从数据库中取出后转换、字符编码转换、大文本块处理(将字符集转成ISO)、字符类型转换,比如将String型变量转换成int型变量等操作,在实际应用中,这是个相当实用的字符串操作类。

    .java文件中GBK编码转UTF-8编码

    在eclispe的项目中,有存在项目字符集和工作空间字符集不匹配,该jar只能将项目文件中的.java结尾的文件转为utf8编码,并且源文件必须为gbk编码的,否则乱码

    CharsetUtils.java

    * 字符编码工具类 , 主要方法:1)获取传入字符串的编码格式 2)根据新的编码格式生成新字符串 /** 7位ASCII字符,也叫作ISO646-US、Unicode字符集的基本拉丁块 */ US_ASCII("US-ASCII","位ASCII字符,也叫作ISO...

    zxing.java源码解析-Specialsymbols:一些字符集编码资料收集

    zxing.java源码解析 ...该篇对字符集编码及java开发web开发应用解析较全面 正则表达式 原码, 反码, 补码 jQuery 设计模式 算法 ZBar 条码 TODO Parcelable在Android中的设计和实现 从聊天记录抓取的github资源 ...

    java实现十六进制字符unicode与中英文转换示例

    当需要对一个unicode十六进制字符串进行编码时,首先做的应该是确认字符集编码格式,在无法快速获知的情况下,通过一下的str4all方法可以达到这一目的

    字符编码学习

    目前Unicode是采用16位编码体系,其字符集内容与 ISO10646的BMP(Basic Multilingual Plane)相同。Unicode于1992年6月通过DIS(Draf International Standard),目前版本V2.0于1996公布,内容包含符号6811个,汉字...

    JAVA字符串操作类CTool.java字符转换类

    比如字符串的查找替换操作、将字符串中的特殊字符转换成Web页中可以安全显示的字符串,转换字符串,从UTF-8到GBK的编码转换,从“GBK”到“ISO8859_1”的字符串转换,大文本块处理(将字符集转成ISO),String型变量...

    字符串(汉字)长度判断

    针对Oracle数据库中汉字在不通的字符集下所占字符长度不通,在保存时可能需要对源字符串的长度进行判断。 实现过程如下 /** * 针对汉字 进行计算长度 * @param string 计算的字符串 * @param ...

    custom-base-64:CustomBase64 Java 类,提供将字节数组编码解码为具有自定义字符集的 Base64 字符串的功能。 不使用填充字符。 不遵循 RFC 3548 或 RFC 4648

    此 CustomBase64 类提供将字节数组编码/解码为 Base64 字符串的功能。 它不遵循 Base64 的 RFC 3548 或 RFC 4648 规范,因为可以指定使用的字符集并且不使用填充字符。 因此,只有用户通过调用 setBase64Charset...

    Java中的String类getBytes()方法详解与实例

    在本文中,我们学习了Java String类的getBytes()方法,它允许将字符串转换为字节数组,并且可以指定字符编码方式。通过实例和代码演示了使用平台默认字符编码和指定UTF-8、ISO-8859-1字符编码的情况。getBytes()方法...

    Java 工具类 包含一些常用的方法

    JavaUtil类中其中包含的方法有: ...5.将文件转换为指定字符编码集的字符串 6.获取指定类的随机实例(传入Class模板) 7.根据指定包名搜索文件 如需使用如上方法,需要将JavaUtil复制到项目中任意位置即可

    Java-Geocoder:开源Java地理编码服务

    Java Geocoder关于PinPoint地理编码项目Java Geocoder是基于Java,Spring,Hibernate,PostgreSQL,美国人口普查数据和辛苦工作建立的开源地理... 地理编码API 此api需要一个地址字符串,并尝试解析和地理编码所述字符

    jchardet-1.1jchardet-1.1jchardet-1.1

    jchardet-1.1 字符编码识别jchardet-1.1 字符编码...例如,一个HTML页面中的数据,如果没有元数据标签明确地指定页面的字符集,就很难确实其编码,将其转换为 Java Unicode字符串时也会误用而终止。符集探测算法代码的

    GSM-PDU模式短信编解码-java代码

    项目中用到了AT指令中的GSM短信息的收发,上网找的代码大多都是C或者C++语言编写...4、代码中实现了PDU模式下7bit编码和UCS2编码这两种常用编码方式下的数据编码与解码 5、代码中实现了对信息中是否包含中文字符的判断

    jchardet jchardet

    jchardet-1.1 字符编码识别jchardet-1.1 字符编码...例如,一个HTML页面中的数据,如果没有元数据标签明确地指定页面的字符集,就很难确实其编码,将其转换为 Java Unicode字符串时也会误用而终止。符集探测算法代码的

Global site tag (gtag.js) - Google Analytics