Мне нужно принимать потоки с разными кодировками и транскодировать их в одну предопределенную кодировку (например, UTF-8). Я знаю, как это сделать с (InputStream
) Reader
/ (OutputStream
) Writer
комбо и буфером массива, но на этот раз я имею дело с ByteChannel
. Естественно, я искал решение CharsetDecoder
/ CharsetEncoding
, но лучшее, с чем я пришел, это:
public static void copy(ReadableByteChannel rbc, Charset in,
WritableByteChannel wbc, Charset out) throws IOException {
ByteBuffer b1 = ByteBuffer.allocateDirect(BUFFER_SIZE);
CharBuffer cb = CharBuffer.allocate(BUFFER_SIZE);
ByteBuffer b2 = ByteBuffer.allocateDirect(BUFFER_SIZE);
CharsetDecoder decoder = in.newDecoder();
decoder.onMalformedInput(CodingErrorAction.REPLACE);
CharsetEncoder encoder = out.newEncoder();
encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
while( rbc.read(b1)!=-1 ){
b1.flip();
decoder.decode(b1, cb, false);
cb.flip();
encoder.encode(cb, b2, false);
b2.flip();
wbc.write(b2);
b2.compact();
cb.compact();
b1.compact();
}
b1.flip();
while (b1.hasRemaining()){
decoder.decode(b1, cb, true);
cb.flip();
encoder.encode(cb, b2, false);
b2.flip();
wbc.write(b2);
b2.compact();
cb.compact();
}
decoder.decode(b1, cb, true);
decoder.flush(cb);
cb.flip();
while (cb.hasRemaining()){
encoder.encode(cb, b2, true);
b2.flip();
wbc.write(b2);
b2.compact();
}
encoder.encode(cb, b2, true);
encoder.flush(b2);
b2.flip();
while (b2.hasRemaining()){
wbc.write(b2);
}
}
Поскольку этот метод является «рабочей лошадкой» в проекте, я должен быть абсолютно уверен, что он завершится независимо от того, какая комбинация BUFFER_SIZE, кодировки и устройства блокировки для вывода дана.
Мои вопросы:
- Есть ли лучший способ опустошения буфера вместо этого каскада циклов while?
- Можно ли игнорировать результаты
encode()
/ decode()
(для переполнений и переполнений)?
Конечно, любая альтернативная идея приветствуется. :)