2008-09-24 11 views

ответ

1

Отвечая на мой собственный вопрос: вы должны вызвать buf.clear() между read с. Предположительно, read висит, потому что буфер заполнен. Правильный код:

 
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(); 
    } 
} 
+0

Подвеска? Глядя на читаемый API, я бы ожидал, что он занят циклом, возвращающим 0 на каждый прочитанный, если буфер заполнен, но это предположение, поскольку в нем явно не указано, что означает «попытки прочитать». Висячие могут означать, что, поскольку вы многократно записываете выходные данные, вы заблокировали вывод. –

+0

Я не проверял подробное поведение цикла. Либо считывает блоки, либо повторно возвращает 0. Сетевой эффект: цикл никогда не заканчивается. –

+0

Я предполагаю, что для блокировки выходного потока должно быть что-то с конечной емкостью, которая не сливается, как круговой буфер - довольно редкий случай. Возможно, я особенный, потому что я обычно использую «зависание», чтобы означать «тупик», а не «живой». –

0

Я бы предположил, что это тупик. In.read (buf) блокирует CharBuffer и предотвращает вызов out.append (buf).

Это предполагает, что CharBuffer использует блокировки (как-то) в реализации. Что говорит API о классе CharBuffer?

Редактировать: Извините, какое-то короткое замыкание в моем мозгу ... Я смутил его чем-то другим.

0

CharBuffers не работают с читателями и писателями так же, как вы могли бы ожидать. В частности, нет метода Writer.append(CharBuffer buf). Метод, вызванный фрагментом вопросов, - Writer.append(CharSequence seq), который просто вызывает seq.toString(). Метод CharBuffer.toString() возвращает строковое значение буфера, но он не сбрасывает буфер. Последующий вызов Reader.read(CharBuffer buf) получает уже полный буфер и поэтому возвращает 0, заставляя цикл продолжать бесконечно.

Хотя это похоже на зависание, оно фактически добавляет содержимое буфера первого чтения к каждому проходу через цикл. Таким образом, вы либо начнете видеть много выходных данных в вашем пункте назначения, либо внутренний буфер писателя будет расти в зависимости от того, как выполняется сценарий.

Как бы это ни было раздражало, я бы рекомендовал реализацию char [], хотя бы потому, что решение CharBuffer завершает строительство по меньшей мере двух новых символов [] каждый проход через цикл.

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); 
    } 
} 

Я бы рекомендовал только с помощью этого, если вам необходимо поддерживать преобразование между двумя кодировками, в противном случае ByteBuffer/канал или байт реализации []/IOStream бы предпочтительнее, даже если вы трубопроводные символы.

Смежные вопросы