Pergunta

Por que o método seguinte está pendurado?

public void pipe(Reader in, Writer out) {
    CharBuffer buf = CharBuffer.allocate(DEFAULT_BUFFER_SIZE);
    while( in.read(buf) >= 0 ) {
      out.append(buf.flip());
    }
}
Foi útil?

Solução

Respondendo minha própria pergunta: você tem que ligar buf.clear() entre reads. Presumivelmente, read está pendurado porque o buffer está cheio. O código correto é

public void pipe(Reader in, Writer out) {
    CharBuffer buf = CharBuffer.allocate(DEFAULT_BUFFER_SIZE);
    while( in.read(buf) >= 0 ) {
      out.append(buf.flip());
      buf.clear();
    }
}

Outras dicas

Eu assumiria que é um impasse. O In.Read (BUF) bloqueia o charbuffer e evita a chamada OUT.Append (BUF).

Isso pressupõe que o CharBuffer use bloqueios (de algum tipo) na implementação. O que a API diz sobre o charbuffer da classe?

EDIT: Desculpe, algum tipo de curto -circuito no meu cérebro ... confundi com outra coisa.

Os charbuffers não trabalham com leitores e escritores da maneira mais limpa possível. Em particular, não há Writer.append(CharBuffer buf) método. O método chamado pelo trecho de pergunta é Writer.append(CharSequence seq), que apenas liga seq.toString(). o CharBuffer.toString() O método retorna o valor da string do buffer, mas não drena o buffer. A chamada subsequente para Reader.read(CharBuffer buf) Obtém um buffer já completo e, portanto, retorna 0, forçando o loop a continuar indefinidamente.

Embora isso pareça um jarro, está de fato anexando o conteúdo do buffer da primeira leitura ao escritor a cada passe pelo loop. Portanto, você começará a ver muita saída no seu destino ou o buffer interno do escritor crescerá, dependendo de como o escritor é implementado.

Por mais irritante que seja, eu recomendaria uma implementação de char [] apenas porque a solução de charbuffer acaba construindo pelo menos dois novos char [] cada passagem pelo loop.

public void pipe(Reader in, Writer out) throws IOException {
    char[] buf = new char[DEFAULT_BUFFER_SIZE];
    int count = in.read(buf);
    while( count >= 0 ) {
        out.write(buf, 0, count);
        count = in.read(buf);
    }
}

Eu recomendo apenas usar isso se você precisar suportar a conversão entre duas codificações de caracteres, caso contrário, uma implementação de bytebuffer/canal ou byte []/iostream seria preferível, mesmo se você estivesse canalizando caracteres.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top