Module java.base
Package java.nio.charset

Class CharsetEncoder

java.lang.Object
java.nio.charset.CharsetEncoder

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

输入字符序列提供在字符缓冲区或一系列这样的缓冲区中。输出字节序列写入字节缓冲区或一系列这样的缓冲区中。编码器应始终通过进行以下方法调用序列(以下简称为编码操作)来使用:

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

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

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

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

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

有两种一般类型的编码错误。如果输入字符序列不是合法的十六位Unicode序列,则将输入视为格式错误。如果输入字符序列合法但无法映射到给定字符集中的有效字节序列,则遇到了一个无法映射字符

如何处理编码错误取决于对该类型错误请求的操作,该操作由CodingErrorAction类的实例描述。可能的错误操作是忽略错误输入,通过返回的CoderResult对象向调用者报告错误,或者用当前替换字节数组替换错误输入。替换最初设置为编码器的默认替换,通常(但并非总是)具有初始值 { (byte)'?' };可以通过replaceWith方法更改其值。

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

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

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

自1.4版本起:
1.4
参见:
  • Constructor Details

    • CharsetEncoder

      protected CharsetEncoder(Charset cs, float averageBytesPerChar, float maxBytesPerChar, byte[] replacement)
      初始化一个新的编码器。新编码器将具有给定的每字符字节数和替换值。
      参数:
      cs - 创建此编码器的字符集
      averageBytesPerChar - 一个正浮点值,指示每个输入字符将产生的预期字节数
      maxBytesPerChar - 一个正浮点值,指示每个输入字符将产生的最大字节数
      replacement - 初始替换;不得为null,必须具有非零长度,不得长于maxBytesPerChar,并且必须是合法的
      抛出:
      IllegalArgumentException - 如果参数的前提条件不成立
    • CharsetEncoder

      protected CharsetEncoder(Charset cs, float averageBytesPerChar, float maxBytesPerChar)
      初始化一个新的编码器。新编码器将具有给定的每字符字节数值,其替换将是字节数组{ (byte)'?' }
      参数:
      cs - 创建此编码器的字符集
      averageBytesPerChar - 一个正浮点值,指示每个输入字符将产生的预期字节数
      maxBytesPerChar - 一个正浮点值,指示每个输入字符将产生的最大字节数
      抛出:
      IllegalArgumentException - 如果参数的前提条件不成立
  • Method Details

    • charset

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

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

      public final CharsetEncoder replaceWith(byte[] newReplacement)
      更改此编码器的替换值。

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

      参数:
      newReplacement - 新替换值;不得为null,必须具有非零长度,不得长于maxBytesPerChar方法返回的值,并且必须是合法的
      返回:
      此编码器
      抛出:
      IllegalArgumentException - 如果参数的前提条件不成立
    • implReplaceWith

      protected void implReplaceWith(byte[] newReplacement)
      报告此编码器的替换值更改。

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

      参数:
      newReplacement - 替换值
    • isLegalReplacement

      public boolean isLegalReplacement(byte[] repl)
      告知给定的字节数组是否是此编码器的合法替换值。

      如果且仅当替换是此编码器字符集中的合法字节序列时,替换才是合法的;也就是说,必须能够将替换解码为一个或多个十六位Unicode字符。

      此方法的默认实现效率不高;通常应该覆盖此方法以提高性能。

      参数:
      repl - 要测试的字节数组
      返回:
      如果且仅当给定的字节数组是此编码器的合法替换值时为true
    • malformedInputAction

      public CodingErrorAction malformedInputAction()
      返回此编码器对格式错误输入的当前操作。
      返回:
      当前格式错误输入操作,永远不为null
    • onMalformedInput

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

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

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

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

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

      参数:
      newAction - 新操作
    • unmappableCharacterAction

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

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

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

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

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

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

      参数:
      newAction - 新操作
    • averageBytesPerChar

      public final float averageBytesPerChar()
      返回每个输入字符产生的平均字节数。此启发式值可用于估计给定输入序列所需的输出缓冲区大小。
      返回:
      每个输入字符产生的平均字节数
    • maxBytesPerChar

      public final float maxBytesPerChar()
      返回每个输入字符将产生的最大字节数。此值可用于计算给定输入序列所需输出缓冲区的最坏情况大小。此值考虑任何必要的与内容无关的前缀或后缀字节,例如字节顺序标记。
      返回:
      每个输入字符将产生的最大字节数
    • encode

      public final CoderResult encode(CharBuffer in, ByteBuffer 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,以便任何剩余的未编码输入将被视为错误的。

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

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

      public final CoderResult flush(ByteBuffer out)
      刷新此编码器。

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

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

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

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

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

      参数:
      out - 输出字节缓冲区
      返回:
      描述终止原因的编码器结果对象,可以是CoderResult.UNDERFLOWCoderResult.OVERFLOW
      抛出:
      IllegalStateException - 如果当前编码操作的上一步是调用flush方法或三参数的encode方法,endOfInput参数的值为true
    • implFlush

      protected CoderResult implFlush(ByteBuffer out)
      刷新此编码器。

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

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

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

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

      返回:
      此编码器
    • implReset

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

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

    • encodeLoop

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

      此方法封装了基本的编码循环,尽可能多地编码字符,直到输入用尽、输出缓冲区空间用尽或遇到编码错误为止。此方法由encode方法调用,该方法处理结果解释和错误恢复。

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

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

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

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

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

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

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

      public boolean canEncode(char c)
      告知此编码器是否能够编码给定的字符。

      如果给定的字符是代理字符,则此方法返回false;这样的字符只有在它们是由高代理字符后跟低代理字符组成的一对时才能解释。可以使用canEncode(CharSequence)方法来测试字符序列是否可以编码。

      此方法可能会修改此编码器的状态;因此,如果已经有编码操作正在进行,则不应调用此方法。

      此方法的默认实现效率不高;通常应该被覆盖以提高性能。

      参数:
      c - 给定的字符
      返回:
      如果此编码器可以编码给定的字符,则返回true
      抛出:
      IllegalStateException - 如果已经有编码操作正在进行
    • canEncode

      public boolean canEncode(CharSequence cs)
      告知此编码器是否能够编码给定的字符序列。

      如果此方法对特定字符序列返回false,则可以通过执行完整的编码操作来获取有关为什么无法编码该序列的更多信息。

      此方法可能会修改此编码器的状态;因此,如果已经有编码操作正在进行,则不应调用此方法。

      此方法的默认实现效率不高;通常应该被覆盖以提高性能。

      参数:
      cs - 给定的字符序列
      返回:
      如果此编码器可以编码给定字符而不抛出任何异常且不执行任何替换,则返回true
      抛出:
      IllegalStateException - 如果已经有编码操作正在进行