Почему определяет CharsetEncoder Java.onMalformedInput () / CharsetDecoder define.возвраты текущее()?

A CharsetDecoder в основном помогает декодировать последовательность bytes в последовательность chars (см. Charset#newDecoder()). На противоположной стороне a CharsetEncoder (см. Charset#newEncoder()) делает обратное: возьмите последовательность chars, и Закодируйте их в последовательность bytes.

CharsetDecoder определяет .onMalformedInput() и это кажется логичным (некоторая последовательность байтов может не переводиться в действительное char последовательности); но почему .onUnmappableCharacter() С момента его ввод-это последовательность байтов?

аналогично, CharsetEncoder определяет .onUnmappableCharacter() что, опять же, логично (например, если ваша кодировка ASCII, вы не можете кодировать ö), но почему он также определения .onMalformedInput() так как его вход является последовательностью символов?

это тем более интригует, что вы не можете получить кодер из декодера и наоборот, и ни один из этих двух классов, похоже, не имеет общего предка...


изменить 1

это действительно можно вызвать .onMalformedInput() на CharsetEncoder. Вы "просто" должны предоставить незаконный char или char последовательности. Программа ниже опирается на тот факт, что в UTF-16 за высоким суррогатом должен следовать низкий суррогат; здесь вместо этого строится двухэлементный массив символов с двумя высокими суррогатами, и делается попытка его кодирования. обратите внимание, как создание String из такой плохо сформированной последовательности символов не выбрасывает никаких исключений все!--47-->:

код:

public static void main(final String... args)
    throws CharacterCodingException
{
    boolean found = false;
    char c = '.';

    for (int i = 0; i < 65536; i++) {
        if (Character.isHighSurrogate((char) i)) {
            c = (char) i;
            found = true;
            break;
        }
    }
    if (!found)
        throw new IllegalStateException();

    System.out.println("found: " + Integer.toHexString(c));
    final char[] foo = { c, c };

    new String(foo); // <-- DOES NOT THROW AN EXCEPTION!!!

    final CharsetEncoder encoder = StandardCharsets.UTF_8.newEncoder()
        .onMalformedInput(CodingErrorAction.REPORT);

    encoder.encode(CharBuffer.wrap(foo));
}

выход:

found: d800
Exception in thread "main" java.nio.charset.MalformedInputException: Input length = 1
    at java.nio.charset.CoderResult.throwException(CoderResult.java:277)
    at java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:798)
    at com.github.fge.largetext.LargeText.main(LargeText.java:166)

правка 2 а теперь, как насчет обратного? Из ответа @Kairos ниже, цитируя manpage:

UnmappableCharacterException-если последовательность байтов, начинающаяся с текущей позиции входного буфера, не может быть сопоставлена с эквивалентной последовательностью символов, а текущее действие unmappable-character CodingErrorAction.Доклад

теперь, что "не может быть сопоставлено с эквивалентной последовательностью символов"?

я играю совсем немного с CharsetDecoders в этот проект и еще предстоит произвести такую ошибку. Я знаю, как воспроизвести ошибку, в которой, например, у вас есть только два байта из трехбайтовой последовательности UTF-8, но это вызывает MalformedInputException. Все, что вам нужно сделать в этом случае, это перезапустить декодирование с последней известной позиции ByteBuffer.

вызов UnmappableCharacterException в основном означало бы, что символ самой кодировки допускает незаконное char будет сгенерирован; или незаконная кодовая точка Unicode.

возможно ли это вообще?

1 ответов


в документах для CharsetEncoder.encode () он заявляет, что он бросает MalformedInputException

Если последовательность символов начинается с текущего входного буфера позиция не является законной шестнадцатиразрядной последовательностью Unicode и текущим искаженным входом действие CodingErrorAction.Доклад

таким образом, вам предоставляется возможность предоставления CodingErrorAction С помощью onMalformedInput Так что если если вы столкнетесь с одной из этих незаконных шестнадцатиразрядных последовательностей Юникода, будет выполнено указанное действие.

аналогично CharsetDecoder.decode ()

UnmappableCharacterException - если последовательность байтов, начиная с текущее положение входного буфера не может быть сопоставлено с эквивалентным последовательность символов и текущее действие unmappable-character CodingErrorAction.Доклад