字符集基础
Character set(字符集):字符的集合,也就是,带有特殊语义的符号。没有内在数字价值,与ASCII,Unicode,甚至是电脑也没有任何的直接联系。Coded character set(编码字符集):一个数值赋给一个字符的集合。把代码赋值给字符,这样它们就可以用特定的字符编码集表达数字的结果。其他的编码字符集可以赋不同的数值到同一个字符上。
Character-encoding scheme(字符编码方案):编码字符集成员到八位字节(8 bit字节)的映射。编码方案定义了如何把字符编码的序列表达为字节序列。原则上,把字符集编码和解码近似视为对象的序列化和反序列化。
通常字符数据编码是用于网络传输或文件存储。编码方案不是字符集,它是映射;但是因为它们之间的紧密联系,大部分编码都与一个独立的字符集相关联。例如,UTF-8,仅用来编码Unicode字符集。
字符集
到JDK1.4 为止,每个JVM实现都需要支持标准字符集,可以随意的支持额外的字符集,但是必须提供这个最大集。JVM没有指定默认字符集,也没有要求是这些标准字符集之一。在JVM启动时确定默认值,取决于潜在的操作系统环境、区域设置、和/或JVM配置。字符集名称不区分大小写,也就是,当比较字符集名称时认为大写字母和小写字母相同。
字符集类
package java.nio.charset;
public abstract class Charset implements Comparable
{
public static boolean isSupported (String charsetName)
public static Charset forName (String charsetName)
public static SortedMap availableCharsets( )
public final String name( )
public final Set aliases( )
public String displayName( )
public String displayName (Locale locale)
public final boolean isRegistered( )
public boolean canEncode( )
public abstract CharsetEncoder newEncoder( );
public final ByteBuffer encode (CharBuffer cb)
public final ByteBuffer encode (String str)
public abstract CharsetDecoder newDecoder( );
public final CharBuffer decode (ByteBuffer bb)
public abstract boolean contains (Charset cs);
public final boolean equals (Object ob)
public final int compareTo (Object ob)
public final int hashCode( )
public final String toString( )
}
Charset类封装特定字符集的永恒信息。Charset是抽取。通过调用静态工厂方法forName()获得具体实例,导入所需字符集的名称。所有的Charset方法都是线程安全的。
isSupported()来确定在JVM运行中当前指定的字符集是否可用。通过Charset SPI机制可以动态安装新的字符集。
一个字符集可以有多个名称。通常它有一个规范名称但是也有零个或多个别名。规范名称或别名都可以通过forName()和isSupported()进行使用。
一些字符集也有历史遗留的名称,它们用于之前的Java平台版本并且向后兼容。字符集的历史名称是由InputStreamReader和OutputStream-Writer类的getEncoding()返回。如果字符集有历史名称,那么它将是规范名称或者Charset的别名之一。
availableCharsets(),将返回在JVM中当前有效的所有字符集。
一旦获取Charset实例的参数,name()方法将返回字符集的规范名称,并且aliases()将给出包含别名的Set。
字符集比较
public abstract class Charset implements Comparable
{
// This is a partial API listing
public abstract boolean contains (Charset cs);
public final boolean equals (Object ob)
public final int compareTo (Object ob)
public final int hashCode( )
public final String toString( )
}
contains()实例方法显示作为参数传入的Charset对象是否被该Charset对象封装的字符集所包含。。该方法不能在运行时动态比较字符集;只有当具体的Charset类确定给出的字符集被包含的情况下才返回true。
如果一个字符集被另一个包含,这不意味着产生的编码字节序列将会等同于给定的输入字符序列。
Charset类明确地覆盖了Object.equals()方法。如果Charset的实例拥有相同的规范名称(由name()返回),它们就被认为是相同的。
与equals()类似的, compareTo()以Charset对象的规范名称为基础,返回结果。用Charset的compareTo()方法进行比较时大小写不计。
hashCode()方法返回由name()方法(区分大小写)返回的String的散列代码。Charset的toString()方法返回规范名称。
字符集编码器
字符集是由一个编码字符集和一个相关编码方案组成的。CharsetEncoder和CharsetDecoder类实现转换方案。
canEncode():表示这个字符集是否允许编码。几乎所有的字符集都支持编
newEncoder() 返回CharsetEncoder对象,可以使用和字符集相关的编码方案把字符序列转化为字节序列。Charset的两个encode() 方法使用方便,用默认值针对和字符集相关的编码器实现编码,两个都返回新ByteBuffer对象,包含符合给定的String或CharBuffer字符的一个编码字节序列。解码器通常都在CharBuffer对象上运行。
charset.encode (CharBuffer.wrap (string)); 等价于
charset.newEncoder( )
.onMalformedInput (CodingErrorAction.REPLACE)
.onUnmappableCharacter (CodingErrorAction.REPLACE)
.encode (charBuffer);
package java.nio.charset;
public abstract class CharsetEncoder
{
public final Charset charset( )
public final float averageBytesPerChar( )
public final float maxBytesPerChar( )
public final CharsetEncoder reset( )
public final ByteBuffer encode (CharBuffer in) throws
CharacterCo dingException
public final CoderResult encode (CharBuffer in, ByteBuffer out,
boolean endOfInput)
public final CoderResult flush (ByteBuffer out)
public boolean canEncode (char c)
public boolean canEncode ( CharSequence cs)
public CodingErrorAction malformedInputAction( )
public final CharsetEncoder onMalformedInput (CodingErrorAction newAction)
public CodingErrorAction unmappableCharacterAction( )
public final CharsetEncoder onUnmappableCharacter (CodingErrorAction newAction)
public final byte [] replacement( )
public boolean isLegalReplacement (byte[] repl)
public final CharsetEncoder replaceWith (byte[] newReplacement) }
CharsetEncoder对象是一个状态转换引擎:字符进去,字节出来。
averageBytesPerChar()方法返回一个浮点值,表示编码集合的字符所需的平均字节数量。该方法作为一个程序的探索很有用,用来确定ByteBuffer的近似尺寸,ByteBuffer需要包含给定字符的编码字节。
maxBytesPerChar() 方法表示在集合中编码单字符需要的最大字节数。这也是一个浮点值。与averageBytesPerChar()类似,该方法被用来按大小排列ByteBuffer。
CharsetEncoder类是一个状态编码引擎,编码器有状态意味着它们不是线程安全的:CharsetEncoder对象不应该在线程中共享。
编码过程:
1 通过调用reset() 方法复位编码器的状态。让编码引擎准备开始产生编码字节流
2 不调用或多次调用encode() 为编码器提供字符,end Ofnput参数false 表示后面可能有更多的字符。给定的CharBuffer 将消耗字符,而编码字节序列将被添加到提供的ByteBuffe r上。返回时,输入CharBuffer可能不是全部为空。可能填入输出ByteBuffer,或者编码器可能需要更多的输入来完成多字符转化。编码器本身可能也保留可以影响序列转化实现的状态。
3 最后一次调用encode() ,针对endOfInput 参数导入true。提供的CharBuffer可能包含额外的需要编码的字符或为空。重要的是endOfInput 在最后的调用上为true。这样就通知编码引擎后面没有输入了,允许它探测有缺陷的输入。
4 调用flush() 方法来完成未完成的编码并输出所有剩下的字节。 当消耗了所有的输入时,当输出ByteBuffer为满时,或者当探测到编码错误时,encode() 方法返回。无论如何,将会返回CoderResult 对象,来表示发生的情况。
结果对象可表示下列结果条件之
1 Underflow(下溢):正常情况,表示需要更多的输入。或者是输入CharBuffer内容不足;或者,如果它不为空,在没有额外的输入的情况下,余下的字符无法进行处理。更新CharBuffer的位置解决被编码器消耗的字符的问题。 在CharBuffer中填入更多的编码字符(首先在缓冲区上调用compact(),如果是非空的情况)并再次用encode() 继续。如果结束了,用空CharBuffer调用encode() 并且endOfInput 为true,之后调用flush() 确保所有的字节都被发送给ByteBuffer。下溢条件总是返回相同的对象实例:CharsetEncoder.UNDERFLOW 的静态类变量。这就使您可以使用返回的对象句柄上的等号运算符(==)来对下溢进行检测。
2 Overflow (上溢):表示编码器充满了输出ByteBuffer并且需要产生更多的编码输出。输入CharBuffer对象可能会或可能不会被耗尽。这是正常条件,不表示出错。您应该消耗ByteBuffer但是不应该扰乱CharBuffer,CharBuffer将更新它的位置,之后再次调用encode() 。重复进行直到得到下溢结果。与下溢类似的,上溢返回一致的实例,CharsetEncoder.OVERFLOW
3 Malformed input(有缺陷的输入):编码时,这个通常意味着字符包含 16 -位的数值,不是有效的Unicode字符。对于解码来说,这意味着解码器遭遇了不识别的字节序列。返回的CoderResult 实例将不是单一的参数,因为它是针对下溢和上溢的
4 Unmappable character (无映射字符):表示编码器不能映射字符或字符的序列到字节上。
编码时,如果编码器遭遇了有缺陷的或不能映射的输入,返回结果对象。您也可以检测独立的字符,或者字符序列,来确定它们是否能被编码 。
package java.nio.charset;
public abstract class CharsetEncoder
{
// This is a partial API listing
public boolean canEncode (char c)
public boolean canEncode (CharSequence cs)
}
canEncode()的两个形式返回boolean结果,表示编码器是否能将给出的输入编码。两种方法都在一个临时的缓冲区内实现输入的编码。这将引起编码器内部状态的改变,所以当编码处理正在进行中时不应调用这些方法。