Почему определяет CharsetEncoder Java.onMalformedInput () / CharsetDecoder define.возвраты текущее()?
A CharsetDecoder
в основном помогает декодировать последовательность bytes
в последовательность char
s (см. Charset#newDecoder()
). На противоположной стороне a CharsetEncoder
(см. Charset#newEncoder()
) делает обратное: возьмите последовательность char
s, и Закодируйте их в последовательность byte
s.
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.Доклад
теперь, что "не может быть сопоставлено с эквивалентной последовательностью символов"?
я играю совсем немного с CharsetDecoder
s в этот проект и еще предстоит произвести такую ошибку. Я знаю, как воспроизвести ошибку, в которой, например, у вас есть только два байта из трехбайтовой последовательности UTF-8, но это вызывает MalformedInputException
. Все, что вам нужно сделать в этом случае, это перезапустить декодирование с последней известной позиции ByteBuffer
.
вызов UnmappableCharacterException
в основном означало бы, что символ самой кодировки допускает незаконное char
будет сгенерирован; или незаконная кодовая точка Unicode.
возможно ли это вообще?
1 ответов
в документах для CharsetEncoder.encode () он заявляет, что он бросает MalformedInputException
Если последовательность символов начинается с текущего входного буфера позиция не является законной шестнадцатиразрядной последовательностью Unicode и текущим искаженным входом действие CodingErrorAction.Доклад
таким образом, вам предоставляется возможность предоставления CodingErrorAction С помощью onMalformedInput Так что если если вы столкнетесь с одной из этих незаконных шестнадцатиразрядных последовательностей Юникода, будет выполнено указанное действие.
аналогично CharsetDecoder.decode ()
UnmappableCharacterException - если последовательность байтов, начиная с текущее положение входного буфера не может быть сопоставлено с эквивалентным последовательность символов и текущее действие unmappable-character CodingErrorAction.Доклад