Почему «перекачивание» CharBuffer зависает?

StackOverflow https://stackoverflow.com/questions/127713

  •  02-07-2019
  •  | 
  •  

Вопрос

Почему следующий метод зависает?

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() между 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();
    }
}

Другие советы

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

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

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

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

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

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

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/Channel или byte[]/IOStream будет предпочтительнее, даже если вы передаете символы по конвейеру.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top