java.nio.charset

异常
错误
java.lang.Object
  继承者 java.nio.charset.CharsetDecoder

public abstract class CharsetDecoder
     
extends Object

能够把特定 charset 中的字节序列转换成 16 位 Unicode 字符序列的引擎。

输入字节序列由字节缓冲区或一系列这样的缓冲区提供。输出字符序列写入字符缓冲区或一系列这样的缓冲区。应该始终通过下面的方法调用序列使用解码器,下文称为解码操作

  1. 通过 reset 方法重置解码器,除非以前未使用过;

  2. 只要有其他的输入数据就应零次或多次调用 decode,为 endOfInput 参数传递 false,在调用之间填充输入缓冲区并刷新输出缓冲区。

  3. 最后时刻调用一次 decode 方法,为 endOfInput 参数传递 true;然后

  4. 调用 flush 方法,这样解码器能够将任何内部状态刷新到输出缓冲区。

每次调用 decode 方法将解码尽可能多的输入缓冲区中的字节,将得到的字符写入输出缓冲区。当需要更多的输入时、输出缓冲区没有足够的空间或出现解码错误时, decode 方法返回。在每种情况下都返回用于描述终止原因的 CoderResult 对象。调用者可根据相应的状况检查此对象并填充输入缓冲区、刷新输出缓冲区或尝试从解码错误中恢复,并再次进行尝试。

有两种常规解码错误类型。如果输入字节序列对此 charset 来说是不合法的,那么就认为输入是错误的。如果输入字节序列是合法的,但不能映射为有效的 Unicode 字符,那么就出现了不可映射的字符

如何处理解码错误取决于为该错误类型所请求的操作,在 CodingErrorAction 类的实例中描述了该类型的错误。可能的错误操作是忽略错误的输入、通过返回的 CoderResult 对象将错误报告给调用者,或者用当前的替换字符串值CodingErrorAction#REPLACE替换错误的输入。 该替换字符串的初始值是 "FD"; 可通过 replaceWith 方法更改此值。

对于错误输入和不可映射的字符错误的默认操作是报告它们。可通过 onMalformedInput 方法更改针对错误输入的错误操作;可通过 onUnmappableCharacter 方法更改不可映射字符错误的操作。

此类设计用来处理解码过程中的许多细节问题,包括错误操作的实现。一个特定 charset 的解码器是此类的具体子类,它只需要实现抽象的 decodeLoop 方法,这个方法封装了基本的解码循环。另外,维护内部状态的子类应该重写 implFlushimplReset 方法。

此类的实例用于多个并发线程是不安全的。

从以下版本开始:
1.4
另请参见:
ByteBuffer, CharBuffer, Charset, CharsetEncoder

构造方法摘要
protected CharsetDecoder(Charset cs, float averageCharsPerByte, float maxCharsPerByte)
          初始化新的解码器。
 
方法摘要
 float averageCharsPerByte()
          返回为每个输入字节生成的平均字符数。
 Charset charset()
          返回创建此解码器的 charset。
 CharBuffer decode(ByteBuffer in)
          把单个输入字节缓冲区的剩余内容解码到新分配的字符缓冲区的便捷方法。
 CoderResult decode(ByteBuffer in, CharBuffer out, boolean endOfInput)
          从给定的输入缓冲区中解码尽可能多的字节,把结果写入给定的输出缓冲区。
protected abstract  CoderResult decodeLoop(ByteBuffer in, CharBuffer out)
          将一个或多个字节解码为一个或多个字符。
 Charset detectedCharset()
          获取此解码器检测到的 charset(可选操作)
 CoderResult flush(CharBuffer out)
          刷新此解码器。
protected  CoderResult implFlush(CharBuffer out)
          刷新此解码器。
protected  void implOnMalformedInput(CodingErrorAction newAction)
          报告此解码器的错误输入操作的更改。
protected  void implOnUnmappableCharacter(CodingErrorAction newAction)
          报告此解码器的不可映射的字符操作的更改。
protected  void implReplaceWith(String newReplacement)
          报告此解码器替换值的更改。
protected  void implReset()
          重置此解码器,清除所有特定于 charset 的内部状态。
 boolean isAutoDetecting()
          通知此解码器是否实现了自动检测 charset。
 boolean isCharsetDetected()
          通知此解码器是否已经检测到了一个 charset(可选操作)
 CodingErrorAction malformedInputAction()
          返回此解码器对错误输入错误的当前操作。
 float maxCharsPerByte()
          返回为每个输入字节生成的最大字符数。
 CharsetDecoder onMalformedInput(CodingErrorAction newAction)
          更改此解码器对错误输入错误的操作。
 CharsetDecoder onUnmappableCharacter(CodingErrorAction newAction)
          更改此解码器对不可映射的字符错误的操作。
 String replacement()
          返回此解码器的替换值。
 CharsetDecoder replaceWith(String newReplacement)
          更改此解码器的替换值。
 CharsetDecoder reset()
          重置此解码器,清除所有内部状态。
 CodingErrorAction unmappableCharacterAction()
          返回此解码器对不可映射的字符错误的当前操作。
 
从类 java.lang.Object 继承的方法
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

构造方法详细信息

CharsetDecoder

protected CharsetDecoder(Charset cs,
                         float averageCharsPerByte,
                         float maxCharsPerByte)
初始化新的解码器。新的解码器具有给定的每字节多少个字符 (chars-per-byte) 值,它的替换值是字符串 "\uFFFD"

参数:
averageCharsPerByte - 一个正的 float 值,指示为每个输入字节所生成的字符数
maxCharsPerByte - 一个正的 float 值,指示为每个输入字节所生成的最大字符数
抛出:
IllegalArgumentException - 如果参数有关的前提不成立
方法详细信息

charset

public final Charset charset()
返回创建此解码器的 charset。

返回:
此解码器的 charset

replacement

public final String replacement()
返回此解码器的替换值。

返回:
返回此解码器的当前替换值,它永远不能为 null,也不能为空

replaceWith

public final CharsetDecoder replaceWith(String newReplacement)
更改此解码器的替换值。

此方法调用 implReplaceWith 方法,检查新的替换值是可接受的后,传递该新替换值。

参数:
newReplacement - 新替换值;一定不能为 null 且长度必须为非零
返回:
此解码器
抛出:
IllegalArgumentException - 如果参数有关的前提不成立

implReplaceWith

protected void implReplaceWith(String newReplacement)
报告此解码器替换值的更改。

此方法的默认实现不执行任何操作。需要通知替换值更改的解码器应该重写此方法。

参数:
newReplacement -

malformedInputAction

public CodingErrorAction malformedInputAction()
返回此解码器对错误输入错误的当前操作。

返回:
当前的错误输入操作,它永远不能为 null

onMalformedInput

public final CharsetDecoder onMalformedInput(CodingErrorAction newAction)
更改此解码器对错误输入错误的操作。

此方法调用 implOnMalformedInput 方法,传递新的操作。

参数:
newAction - 新的操作;一定不能为 null
返回:
此解码器
抛出:
IllegalArgumentException - 如果参数有关的前提不成立

implOnMalformedInput

protected void implOnMalformedInput(CodingErrorAction newAction)
报告此解码器的错误输入操作的更改。

此方法的默认实现不执行任何操作。需要通知错误输入操作更改的解码器应该重写此方法。


unmappableCharacterAction

public CodingErrorAction unmappableCharacterAction()
返回此解码器对不可映射的字符错误的当前操作。

返回:
当前的不可映射的字符操作,它永远不能为 null

onUnmappableCharacter

public final CharsetDecoder onUnmappableCharacter(CodingErrorAction newAction)
更改此解码器对不可映射的字符错误的操作。

此方法调用 implOnUnmappableCharacter 方法,传递新的操作。

参数:
newAction - 新的操作;一定不能为 null
返回:
此解码器
抛出:
IllegalArgumentException - 如果参数有关的前提不成立

implOnUnmappableCharacter

protected void implOnUnmappableCharacter(CodingErrorAction newAction)
报告此解码器的不可映射的字符操作的更改。

此方法的默认实现不执行任何操作。需要通知不可映射的字符操作更改的解码器应该重写此方法。


averageCharsPerByte

public final float averageCharsPerByte()
返回为每个输入字节生成的平均字符数。此试探值可用来估算给定输入序列所需的输出缓冲区大小。

返回:
每个输入字节生成的平均字符数

maxCharsPerByte

public final float maxCharsPerByte()
返回为每个输入字节生成的最大字符数。此值可用来计算给定输入序列最坏情况下所需的输出缓冲区大小。

返回:
每个输入字节生成的最大字符数

decode

public final CoderResult decode(ByteBuffer in,
                                CharBuffer out,
                                boolean endOfInput)
从给定的输入缓冲区中解码尽可能多的字节,把结果写入给定的输出缓冲区。

应该从各缓冲区的当前位置开始进行读取和写入。最多将读取 in.remaining() 个字节,最多将写入 out.remaining() 个字符。前移缓冲区的位置,以反映字节读取和写入字符,但是其标记和界限将无法修改。

除了从输入缓冲区读取字节和向输出缓冲区写入字符,此方法还返回一个 CoderResult 对象来描述它终止的原因:

  • CoderResult.UNDERFLOW 指示已解码尽可能多的输入缓冲区。如果没有进一步的输入,则调用者可以进行到解码操作的下一个步骤。否则,应该使用进一步的输入再次调用此方法。

  • CoderResult.OVERFLOW 指示该输出缓冲区中没有足够空间来解码任何更多字节。应该使用具有更多剩余字符的输出缓冲区再次调用此方法。这通常是通过排空输出缓冲区的所有解码字符来完成的。

  • CoderResult#malformedForLengthmalformed-input 结果指示已检测到错误输入错误。错误的字节起始于输入缓冲区(可能向前增加)的位置;错误字节数可以通过调用结果对象的 length 方法来确定。这种情况只适用于此解码器的错误输入的动作CodingErrorAction.REPORT 的情况下;否则将像请求的那样忽略或替换错误的输入。

  • unmappable-character 结果指示已检测到不可映射的字符错误。解码不可映射的字符的字节起始于输入缓冲区(可能向前增加)的位置;这种字节的数目可以通过调用结果对象的 length 方法来确定。这种情况只适用于此解码器的不可映射的字符的动作CodingErrorAction.REPORT的情况下;否则将像请求的那样忽略或替换不可映射的字符。

在任一情况下,如果在相同的解码操作中调用此方法,则要注意保留输入缓冲区中剩余的所有字节,以便可提供给下一次调用使用。

endOfInput 参数通知此方法除了给定输入缓冲区包含的内容,调用者是否能提供更多的输入。如果可能提供其他的输入,则调用者应该为此参数传递 false;如果不能提供更多的输入,则调用者应该传递 true。实际上在一次调用中传递 false,但后来发现实际上没有更多的输入可用是相当普遍的,这不是错误。但关键是,在此方法的一系列调用中,最后一次调用总是传递 true,这样所有剩余的未解码输入都作为错误输入处理。

此方法通过调用 decodeLoop 方法、解释它的结果、处理错误情况并重新调用(如有必要)来完成其工作。

参数:
in - 输入字节缓冲区
out - 输出字符缓冲区
endOfInput - 当且仅当调用者除了给定缓冲区中的内容外不提供其他输入字节时才为 true
返回:
描述终止原因的 CoderResult 对象
抛出:
IllegalStateException - 如果解码操作已在进行中并且前面的步骤不是调用 reset 方法,也不是为 endOfInput 参数使用 false 来调用此方法,也不是为 endOfInput 参数使用 true 来调用此方法,而是一个指示未完成解码操作的返回值
CoderMalfunctionError - 如果对 decodeLoop 方法的调用抛出不可预料的异常

flush

public final CoderResult flush(CharBuffer out)
刷新此解码器。

一些解码器维护内部状态,并且一旦读取完所有的输入序列后,可能需要向输出缓冲区写入一些最终字符。

任何其他输出写入输出缓冲区时都要从缓冲区的当前位置开始。最多将写入 out.remaining() 个字符。缓冲区的位置要相应地向前移动,但是其标记和界限将无法修改。

如果此方法成功完成,则它返回 CoderResult.UNDERFLOW。如果输出缓冲区没有足够的空间,则它返回 CoderResult.OVERFLOW。如果发生这种情况,那么为了完成当前的解码操作,必须使用具有更多空间的输出缓冲区再次调用此方法。

如果此解码器已经刷新,则调用此方法无效。

此方法调用 implFlush 方法来执行实际的刷新操作。

参数:
out - 输出字符缓冲区
返回:
一个 CoderResult 对象,可能是 CoderResult.UNDERFLOWCoderResult.OVERFLOW
抛出:
IllegalStateException - 如果当前解码操作的前一步既不是调用 flush 方法,也不是为 endOfInput 参数使用 true 来调用三参数的 decode 方法

implFlush

protected CoderResult implFlush(CharBuffer out)
刷新此解码器。

此方法的默认实现不执行任何操作,并且始终返回 CoderResult.UNDERFLOW。对于那些一旦读取完整个的输入序列后,可能需要向输出缓冲区写入最终字符的解码器而言,应该重写此方法。

参数:
out - 输出字符缓冲区
返回:
一个 CoderResult 对象,可能是 CoderResult.UNDERFLOWCoderResult.OVERFLOW

reset

public final CharsetDecoder reset()
重置此解码器,清除所有内部状态。

此方法重置与 charset 无关的状态,并且为了执行所有特定于 charset 的重置操作,还会调用 implReset 方法。

返回:
此解码器

implReset

protected void implReset()
重置此解码器,清除所有特定于 charset 的内部状态。

此方法的默认实现不执行任何操作。维护内部状态的解码器应该重写此方法。


decodeLoop

protected abstract CoderResult decodeLoop(ByteBuffer in,
                                          CharBuffer out)
将一个或多个字节解码为一个或多个字符。

此方法封装了基本的解码循环,在用完输入、用完输出缓冲区的空间或遇到解码错误之前解码尽可能多的字节。此方法由 decode 方法调用,decode 方法处理结果解释和错误恢复。

应该从各缓冲区的当前位置开始进行读取和写入。最多将读取 in.remaining() 个字节,最多将写入 out.remaining() 个字符。前移缓冲区的位置,以反映字节读取和写入字符,但是其标记和界限将无法修改。

此方法返回一个 CoderResult 对象描述它终止的原因,其方式和 decode 方法的相同。大多数此方法的实现处理解码错误的方式是由 decode 方法返回一个用来解释错误的相应结果对象。最优的实现可能是检查相关的错误操作并且自己实现该操作。

此方法的一种实现可能在接收到足够的输入之前,通过返回 CoderResult.UNDERFLOW 来执行任意的 lookahead。

参数:
in - 输入字节缓冲区
out - 输出字符缓冲区
返回:
描述终止原因的 CoderResult 对象

decode

public final CharBuffer decode(ByteBuffer in)
                        throws CharacterCodingException
把单个输入字节缓冲区的剩余内容解码到新分配的字符缓冲区的便捷方法。

此方法实现完整的解码操作;也就是说,它重置解码器,然后解码给定字节缓冲区中的字节,最后刷新此解码器。因此如果正在进行解码操作,则不应该调用此方法。

参数:
in - 输入字节缓冲区
返回:
新分配的字符缓冲区,包含解码操作结果。该缓冲区的位置是零,并且它的界限是在最后写入的字符之后。
抛出:
IllegalStateException - 如果已经进行解码操作
MalformedInputException - 如果从输入缓冲区当前位置开始的字节序列对于此 charset 是不合法的,并且当前的错误输入操作是 CodingErrorAction.REPORT
UnmappableCharacterException - 如果从输入缓冲区当前位置开始的字节序列不能映射到等同的字符序列,并且当前的不可映射的字符操作是 CodingErrorAction.REPORT
CharacterCodingException

isAutoDetecting

public boolean isAutoDetecting()
通知此解码器是否实现了自动检测 charset。

此方法的默认实现总是返回 false;为了返回 true,应该由自动检测解码器重写此方法。

返回:
当且仅当此解码器实现自动检测 charset 时才返回 true

isCharsetDetected

public boolean isCharsetDetected()
通知此解码器是否已经检测到了一个 charset (可选操作)

如果此解码器实现了自动检测 charset,那么在解码操作期间的某个点上此方法可能开始返回 true,以指示在输入字节序列中检测到一个具体的 charset。一旦发生这种情况,就可以调用 detectedCharset 方法来获取检测到 charset。

此方法返回 false 并不表示尚未解码任何字节。一些自动检测解码器能够解码某些(甚至全部)输入字节序列,而不是固定于某个特定的 charset。

此方法的默认实现总是抛出 UnsupportedOperationException;一旦确定了输入 charset,那么为了返回 true,自动检测解码器应该重写此方法。

返回:
当且仅当此解码器检测到具体的 charset 时才返回 true
抛出:
UnsupportedOperationException - 如果此解码器没有实现自动检测 charset

detectedCharset

public Charset detectedCharset()
获取此解码器检测到的 charset (可选操作)

如果此解码器实现自动检测 charset,那么一旦检测到该 charset,则此方法返回实际的 charset。之后,此方法在当前的解码操作过程中都返回相同的值。如果尚未读取足够的输入字节来确定实际的 charset,则此方法抛出 IllegalStateException

此方法的默认实现总是抛出 UnsupportedOperationException;为了返回适当的值,应该由自动检测解码器重写此方法。

返回:
此自动检测解码器检测到的 charset,如果尚未确定 charset,则返回 null
抛出:
IllegalStateException - 如果尚未读取足够的字节来确定 charset
UnsupportedOperationException - 如果此解码器没有实现自动检测 charset