Как правильно расширить класс Java FilterOutputStream? - PullRequest
0 голосов
/ 02 июля 2010

Я хотел бы примерно отслеживать ход загрузки файла.Я знаю, что могу переопределить MultipartEntity и заставить метод writeTo (OutputStream out) записывать в класс FilterOutputStream, который я создал, чтобы обернуть InputStream по умолчанию.Для получения полной информации о том, как я это сделал, см. Мой ответ здесь .

Однако при ближайшем рассмотрении учитывается каждый отправленный байт дважды!Я пошел к документации, чтобы увидеть, что случилось.Похоже, что метод FilterOutputStream write (byte [], int, int) просто вызывает метод FilterOutputStream write (byte) в цикле.Он рекомендует подклассы, чтобы обеспечить более эффективный метод.Я бы предположил, что это включает в себя вызов базового метода OutputStream write (byte [], int, int) и надеется, что базовый OutputStream имеет лучший метод проталкивания байтов в поток (рекомендующие подклассы OutputStream переопределяют этот метод и выполняют лучшую работучем просто зацикливание на методе OutputStream # write (byte)).

Это то место, где я нахожусь в затруднительном положении.Я не могу гарантировать, что MultipartEntity # writeTo (OutputStream) всегда будет приводить к вызову OutputStream.write (byte [], int, int), поэтому, если я посчитаю байты, отправленные туда, я могу пропустить некоторые, отправленные с использованиемметод записи (байт).Однако я не могу рассчитывать на метод write (byte), потому что метод OutputStream.write (byte [], int, int) может никогда не вызвать метод write (byte).

Одним из ответов является вызов super.write (byte [], int, int) внутри метода write (byte [], int, int) моего подкласса.Затем я знаю, что это просто зацикливает метод записи (байта), записывая по одному байту за раз.Затем я могу посчитать все байты, записанные внутри метода записи (байта).Однако это неэффективно, и документы прямо рекомендуют против этого.Я уверен, что некоторым подклассам OutputStream удается записать несколько потоков в поток одновременно, поэтому глупо не использовать это преимущество.

Итак, как правильно переопределить FilterOutputStream, чтобы он был эффективным и учитывал все отправленные байты?

Извините, если это долго, я сделал это вики на случай, если кто-нибудь может описать проблему лучше, чем я.

1 Ответ

3 голосов
/ 02 июля 2010

Просто вызовите write(byte[] b, int off, int len) в основном потоке, когда тот же метод вызывается в вашем потоке подсчета. Это никогда не приведет к вызову метода write(byte b) в подсчитывающем потоке.

Кроме того, ваш CountingOutputStream в связанном ответе имеет ряд других проблем.

  1. Он имеет собственную ссылку на упакованный поток вывода, хотя FilterOutputStream хранит его для вас в защищенном поле с именем out.
  2. Он записывает len байтов в упакованный поток при вызове write(byte[] b, int off, int len), но добавляет только 1 к числу переданных байтов.
  3. Не увеличивает байты, переданные в write(byte b).
...