Module java.base
Package java.nio.charset

Class CharsetDecoder

java.lang.Object
java.nio.charset.CharsetDecoder

public abstract class CharsetDecoder extends Object
一个可以将特定字符集中的字节序列转换为十六位Unicode字符序列的引擎。

输入字节序列以字节缓冲区或一系列这样的缓冲区的形式提供。输出字符序列写入字符缓冲区或一系列这样的缓冲区。通过进行以下一系列方法调用来始终使用解码器,后文将其称为解码操作

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

  2. 调用decode方法零次或多次,只要可能还有额外的输入可用,传递false作为endOfInput参数,并在调用之间填充输入缓冲区并刷新输出缓冲区;

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

  4. 调用flush方法,以便解码器可以将任何内部状态刷新到输出缓冲区。

每次调用decode方法将尽可能多地从输入缓冲区解码字节,将生成的字符写入输出缓冲区。当需要更多输入时,输出缓冲区中没有足够的空间,或者发生解码错误时,CoderResult对象将返回以描述终止原因。调用者可以检查此对象并填充输入缓冲区,刷新输出缓冲区,或者适当时尝试从解码错误中恢复,并重试。

有两种一般类型的解码错误。如果输入字节序列对于此字符集不合法,则将输入视为格式错误。如果输入字节序列合法但无法映射到有效的Unicode字符,则遇到了一个无法映射的字符

如何处理解码错误取决于对该类型错误请求的操作,该操作由CodingErrorAction类的实例描述。可能的错误操作是忽略错误输入,通过返回的CoderResult对象向调用者报告错误,或者用当前替换字符串的当前值替换错误输入。替换的初始值为"\uFFFD";可以通过replaceWith方法更改其值。

对于格式错误输入和无法映射字符错误,默认操作是报告它们。格式错误输入操作可以通过onMalformedInput方法更改;无法映射字符操作可以通过onUnmappableCharacter方法更改。

此类旨在处理解码过程的许多细节,包括错误操作的实现。特定字符集的解码器,即此类的具体子类,只需实现抽象的decodeLoop方法,该方法封装了基本的解码循环。维护内部状态的子类还应该覆盖implFlushimplReset方法。

此类的实例不适合多个并发线程使用。

自:
1.4
参见:
  • Constructor Details

    • CharsetDecoder

      protected CharsetDecoder(Charset cs, float averageCharsPerByte, float maxCharsPerByte)
      初始化一个新的解码器。新的解码器将具有给定的每字节字符数值,并且其替换将是字符串"\uFFFD"
      参数:
      cs - 创建此解码器的字符集
      averageCharsPerByte - 一个正浮点值,指示每个输入字节将产生的预期字符数
      maxCharsPerByte - 一个正浮点值,指示每个输入字节将产生的最大字符数
      抛出:
      IllegalArgumentException - 如果参数的前提条件不成立
  • Method Details

    • charset

      public final Charset charset()
      返回创建此解码器的字符集。
      返回:
      此解码器的字符集
    • replacement

      public final String replacement()
      返回此解码器的替换值。
      返回:
      此解码器的当前替换值,永远不为null且永远不为空
    • replaceWith

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

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

      参数:
      newReplacement - 新替换值;不得为null,必须具有非零长度,并且不得长于maxCharsPerByte方法返回的值
      返回:
      此解码器
      抛出:
      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)
      报告此解码器的格式错误输入操作更改。

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

      参数:
      newAction - 新操作
    • unmappableCharacterAction

      public CodingErrorAction unmappableCharacterAction()
      返回此解码器对无法映射字符错误的当前操作。
      返回:
      当前无法映射字符操作,永远不为null
    • onUnmappableCharacter

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

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

      参数:
      newAction - 新操作;不得为null
      返回:
      此解码器
      抛出:
      IllegalArgumentException - 如果参数的前提条件不成立
    • implOnUnmappableCharacter

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

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

      参数:
      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表示输出缓冲区中没有足够的空间来解码更多字节。应使用具有更多剩余字符的输出缓冲区再次调用此方法。通常通过从输出缓冲区中排出任何已解码的字符来完成此操作。

      • 一个malformed-input结果表示检测到了格式错误的输入错误。格式错误的字节从输入缓冲区的(可能已增加的)位置开始;可以通过调用结果对象的length方法来确定格式错误的字节数。仅当此解码器的格式错误操作CodingErrorAction.REPORT时才适用此情况;否则将根据请求忽略或替换格式错误的输入。

      • 一个unmappable-character结果表示检测到了无法映射的字符错误。解码无法映射字符的字节从输入缓冲区的(可能已增加的)位置开始;可以通过调用结果对象的length方法来确定这些字节的数量。仅当此解码器的无法映射字符操作CodingErrorAction.REPORT时才适用此情况;否则将根据请求忽略或替换无法映射的字符。

      无论如何,如果此方法在相同的解码操作中要重新调用,则应小心保留输入缓冲区中剩余的任何字节,以便它们可用于下一次调用。

      endOfInput参数告知此方法调用者是否可以提供超出给定输入缓冲区中包含的内容的进一步输入。如果有可能提供额外的输入,则调用者应为此参数传递false;如果没有可能提供进一步的输入,则调用者应传递true。在一次调用中传递false并且后来发现实际上没有更多的输入是不错误的,事实上这是非常常见的。然而,最终调用此方法的一系列调用总是应该传递true,以便任何剩余的未解码输入将被视为格式错误处理。

      此方法通过调用decodeLoop方法,解释其结果,处理错误条件,并根据需要重新调用它来工作。

      参数:
      in - 输入字节缓冲区
      out - 输出字符缓冲区
      endOfInput - true表示调用者除了给定缓冲区中的字节外无法提供其他输入字节
      返回:
      描述终止原因的编码器结果对象
      抛出:
      IllegalStateException - 如果解码操作已经在进行中,并且上一步既不是调用reset方法,也不是带有false值的此方法的调用endOfInput参数,也不是带有true值的此方法但返回值指示了不完整的解码操作
      CoderMalfunctionError - 如果调用decodeLoop方法抛出意外异常
    • flush

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

      某些解码器保持内部状态,可能需要在整个输入序列被读取后向输出缓冲区写入一些最终字符。

      任何额外的输出将从其当前位置开始写入输出缓冲区。最多将写入out.remaining()字符。缓冲区的位置将适当地前进,但其标记和限制不会被修改。

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

      如果此解码器已经被刷新,则调用此方法不会产生任何效果。

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

      参数:
      out - 输出字符缓冲区
      返回:
      描述终止原因的编码器结果对象,要么是CoderResult.UNDERFLOW,要么是CoderResult.OVERFLOW
      抛出:
      IllegalStateException - 如果当前解码操作的上一步是调用flush方法或带有true值的三参数decode方法
    • implFlush

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

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

      参数:
      out - 输出字符缓冲区
      返回:
      描述终止原因的编码器结果对象,要么是CoderResult.UNDERFLOW,要么是CoderResult.OVERFLOW
    • reset

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

      此方法重置与字符集无关的状态,并调用implReset方法以执行任何特定于字符集的重置操作。

      返回:
      此解码器
    • implReset

      protected void implReset()
      重置此解码器,清除任何特定于字符集的内部状态。

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

    • decodeLoop

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

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

      缓冲区从它们的当前位置开始读取和写入。最多将读取in.remaining()字节,并且最多将写入out.remaining()字符。缓冲区的位置将被移动以反映读取的字节和写入的字符,但其标记和限制不会被修改。

      此方法返回一个CoderResult对象,以描述其终止原因,方式与decode方法相同。此方法的大多数实现将通过返回适当的结果对象来处理解码错误,以供decode方法解释。优化的实现可能会检查相关的错误操作并自行实现该操作。

      此方法的实现可以通过返回CoderResult.UNDERFLOW执行任意前瞻,直到它接收到足够的输入。

      参数:
      in - 输入字节缓冲区
      out - 输出字符缓冲区
      返回:
      描述终止原因的编码器结果对象
    • decode

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

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

      参数:
      in - 输入字节缓冲区
      返回:
      包含解码操作结果的新分配字符缓冲区。缓冲区的位置将为零,其限制将跟随最后写入的字符。
      抛出:
      IllegalStateException - 如果解码操作已在进行中
      MalformedInputException - 如果从输入缓冲区的当前位置开始的字节序列对于此字符集不合法,并且当前的错误处理操作为CodingErrorAction.REPORT
      UnmappableCharacterException - 如果从输入缓冲区的当前位置开始的字节序列无法映射到等效的字符序列,并且当前的不可映射字符操作为CodingErrorAction.REPORT
      CharacterCodingException - MalformedInputException如果从输入缓冲区的当前位置开始的字节序列对于此字符集不合法,并且当前的错误处理操作为CodingErrorAction.REPORTUnmappableCharacterException如果从输入缓冲区的当前位置开始的字节序列无法映射到等效的字符序列,并且当前的不可映射字符操作为CodingErrorAction.REPORT
      OutOfMemoryError - 如果无法为输入字节缓冲区的请求大小分配输出字符缓冲区
    • isAutoDetecting

      public boolean isAutoDetecting()
      告诉此解码器是否实现自动检测字符集。

      此方法的默认实现始终返回false;自动检测解码器应重写此方法以返回true

      返回:
      true仅当此解码器实现自动检测字符集时
    • isCharsetDetected

      public boolean isCharsetDetected()
      告诉此解码器是否已检测到字符集  (可选操作)

      如果此解码器实现自动检测字符集,则在解码操作期间的某个时间点,此方法可能开始返回true以指示已在输入字节序列中检测到特定字符集。一旦发生这种情况,就可以调用detectedCharset方法来检索检测到的字符集。

      此方法返回false并不意味着尚未解码任何字节。一些自动检测解码器能够解码部分或全部输入字节序列而不固定特定字符集。

      此方法的默认实现始终抛出一个UnsupportedOperationException;自动检测解码器应重写此方法以在确定输入字符集后返回true

      返回:
      true仅当此解码器已检测到特定字符集时
      抛出:
      UnsupportedOperationException - 如果此解码器不实现自动检测字符集
    • detectedCharset

      public Charset detectedCharset()
      检索此解码器检测到的字符集  (可选操作)

      如果此解码器实现自动检测字符集,则此方法在检测到实际字符集后返回该实际字符集。在此点之后,此方法在当前解码操作的持续时间内返回相同的值。如果尚未读取足够的输入字节以确定实际字符集,则此方法会抛出一个IllegalStateException

      此方法的默认实现始终抛出一个UnsupportedOperationException;自动检测解码器应重写此方法以返回适当的值。

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