Moin allerseits,
ich hoffe, ich bin im richtigen Forum ... Ich war mal wieder in der Situation, einen Writer für einen OutputStream vorzumachen. Es gibt dafür eine Implementation, die in zahlreichen Foren mit dem Hinweis des schlechten Stils zu finden ist, die für jeden write()-Aufruf die Bytes mit new String(byte[], String charset) konvertiert.
In den meisten Fällen würde ich einen anderen Weg suchen, der den Einsatz eines InputStreamReaders erlaubt. Aber es gibt Fälle, in denen ein Object eine Methode hat, seinen Inhalt auf einen OutputStream zu schreiben. Wenn man nun weiß, dass es sich um einen UTF-8 Character-Stream handelt, möchte man möglicherweise direkt auf einen Writer schreiben.
Ich habe nun diese Klasse mit einem java.nio.CharsetDecoder umgesetzt.
Was haltet Ihr davon?
Gruß, jpv.
ich hoffe, ich bin im richtigen Forum ... Ich war mal wieder in der Situation, einen Writer für einen OutputStream vorzumachen. Es gibt dafür eine Implementation, die in zahlreichen Foren mit dem Hinweis des schlechten Stils zu finden ist, die für jeden write()-Aufruf die Bytes mit new String(byte[], String charset) konvertiert.
In den meisten Fällen würde ich einen anderen Weg suchen, der den Einsatz eines InputStreamReaders erlaubt. Aber es gibt Fälle, in denen ein Object eine Methode hat, seinen Inhalt auf einen OutputStream zu schreiben. Wenn man nun weiß, dass es sich um einen UTF-8 Character-Stream handelt, möchte man möglicherweise direkt auf einen Writer schreiben.
Ich habe nun diese Klasse mit einem java.nio.CharsetDecoder umgesetzt.
Was haltet Ihr davon?
Gruß, jpv.
Code:
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
public class WriterOutputStream extends OutputStream
{
private final ByteBuffer bbuf;
private final CharBuffer cbuf;
private final CharsetDecoder csd;
private final Writer out;
public WriterOutputStream(String charset, Writer pOut)
{
this(Charset.forName(charset).newDecoder(), pOut);
}
public WriterOutputStream(CharsetDecoder pCsd, Writer pOut)
{
csd = pCsd;
out = pOut;
bbuf = ByteBuffer.allocate(8);
bbuf.limit(0);
cbuf = CharBuffer.allocate(8);
}
@Override
public void write(int b) throws IOException
{
if (bbuf.remaining() > 0)
bbuf.compact();
else
bbuf.clear();
bbuf.put((byte) b);
bbuf.limit(bbuf.position());
bbuf.position(0);
cbuf.clear();
csd.decode(bbuf, cbuf, false);
if (cbuf.position() > 0)
out.write(cbuf.array(), cbuf.arrayOffset(), cbuf.position());
}
@Override
public void write(byte[] b, int off, int len) throws IOException
{
while (len > 0) {
if (bbuf.remaining() > 0)
bbuf.compact();
else
bbuf.clear();
int wlen = len > bbuf.remaining() ? bbuf.remaining() : len;
bbuf.put(b, off, wlen);
len -= wlen;
off += wlen;
bbuf.limit(bbuf.position());
bbuf.position(0);
cbuf.clear();
csd.decode(bbuf, cbuf, false);
if (cbuf.position() > 0)
out.write(cbuf.array(), cbuf.arrayOffset(), cbuf.position());
}
}
@Override
public void flush() throws IOException
{
out.flush();
}
@Override
public void close() throws IOException
{
try {
cbuf.clear();
csd.decode(bbuf, cbuf, true);
csd.flush(cbuf);
if (cbuf.position() > 0)
out.write(cbuf.array(), cbuf.arrayOffset(), cbuf.position());
out.flush();
} catch (Exception e) {
IOUtil.throwIOE(e);
} finally {
out.close();
}
}
}