Как показать входящие байты в процентах в DataInputStream? [Дубликат]

Проблема связана с движком таблицы, который MyISAM. Транзакция способна откат после того, как я изменил движок на InnoDB.

Настройка hibernate.dialect на org.hibernate.dialect.MySQLInnoDBDialect гарантирует создание таблицы с InnoDB в будущем.

9
задан David Moles 10 December 2010 в 21:25
поделиться

5 ответов

Вот довольно простая реализация, которая запускает PropertyChangeEvent s при чтении дополнительных байтов. Некоторые предостережения:

  • Класс не поддерживает операции mark или reset, хотя их было бы легко добавить.
  • Класс не проверяет, число байтов, считанных когда-либо превышающее максимальное количество ожидаемых байтов, хотя это всегда может быть обработано кодом клиента при отображении прогресса.
  • Я не тестировал код.

Код:

public class ProgressInputStream extends FilterInputStream {
    private final PropertyChangeSupport propertyChangeSupport;
    private final long maxNumBytes;
    private volatile long totalNumBytesRead;

    public ProgressInputStream(InputStream in, long maxNumBytes) {
        super(in);
        this.propertyChangeSupport = new PropertyChangeSupport(this);
        this.maxNumBytes = maxNumBytes;
    }

    public long getMaxNumBytes() {
        return maxNumBytes;
    }

    public long getTotalNumBytesRead() {
        return totalNumBytesRead;
    }

    public void addPropertyChangeListener(PropertyChangeListener l) {
        propertyChangeSupport.addPropertyChangeListener(l);
    }

    public void removePropertyChangeListener(PropertyChangeListener l) {
        propertyChangeSupport.removePropertyChangeListener(l);
    }

    @Override
    public int read() throws IOException {
        int b = super.read();
        updateProgress(1);
        return b;
    }

    @Override
    public int read(byte[] b) throws IOException {
        return (int)updateProgress(super.read(b));
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        return (int)updateProgress(super.read(b, off, len));
    }

    @Override
    public long skip(long n) throws IOException {
        return updateProgress(super.skip(n));
    }

    @Override
    public void mark(int readlimit) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void reset() throws IOException {
        throw new UnsupportedOperationException();
    }

    @Override
    public boolean markSupported() {
        return false;
    }

    private long updateProgress(long numBytesRead) {
        if (numBytesRead > 0) {
            long oldTotalNumBytesRead = this.totalNumBytesRead;
            this.totalNumBytesRead += numBytesRead;
            propertyChangeSupport.firePropertyChange("totalNumBytesRead", oldTotalNumBytesRead, this.totalNumBytesRead);
        }

        return numBytesRead;
    }
}
11
ответ дан Adamski 18 August 2018 в 21:57
поделиться
  • 1
    Неплохо. Вероятно, я бы забыл skip(). :) – David Moles 27 August 2009 в 09:24
  • 2
    @David: Чтобы быть честным, реализация skip означала введение гадостей (int), поэтому, если вы знаете, что вам это не нужно, я бы тоже выбрал UnsupportedOperationException. – Adamski 27 August 2009 в 09:26
  • 3
    Также вам нужно проверить, что super.read() не возвращает отрицательный (конец данных). – PhoneixS 24 February 2014 в 12:59
  • 4
    Я думаю, что там все еще есть ошибка. Реализация read(byte[]b) должна быть только return read(b, 0, b.length); ( без обновления прогресса). В текущей реализации вызов read(byte[]b) заставляет считанные байты считаться дважды , потому что реализация FilterInputStream#read(byte[]b) прямо вызывает read(byte[]b,int off,int len). – Marco13 12 June 2016 в 23:31

Если вы создаете приложение GUI, всегда есть ProgressMonitorInputStream . Если нет никакого GUI, связанного с оберткой InputStream в том, как вы описываете, это не проблема и занимает меньше времени, чем сообщение здесь.

1
ответ дан Bombe 18 August 2018 в 21:57
поделиться
  • 1
    Да, я посмотрел на это. Это приложение с графическим интерфейсом, но оно довольно сложное, а отчет о прогрессе - это не просто вопрос о выпуске стандарта ProgressMonitor. Обертка InputStream займет меньше времени, чем вопрос, но я никогда не узнаю, есть ли у кого-то лучшая идея. – David Moles 27 August 2009 в 09:12

Пакет Guava com.google.common.io может помочь вам немного. Следующее - нескомпилированное и непроверенное, но должно поместить вас на правильный путь.

long total = file1.length();
long progress = 0;
final OutputStream out = new FileOutputStream(file2);
boolean success = false;
try {
  ByteStreams.readBytes(Files.newInputStreamSupplier(file1),
      new ByteProcessor<Void>() {
        public boolean processBytes(byte[] buffer, int offset, int length)
            throws IOException {
          out.write(buffer, offset, length);
          progress += length;
          updateProgressBar((double) progress / total);
          // or only update it periodically, if you prefer
        }
        public Void getResult() {
          return null;
        }
      });
  success = true;
} finally {
  Closeables.close(out, !success);
}

Это может показаться большим количеством кода, но я считаю, что это будет наименее, с чего вам это удастся. (обратите внимание, что другие ответы на этот вопрос не дают примеров кода complete , поэтому их сложно сравнивать).

5
ответ дан Kevin Bourrillion 18 August 2018 в 21:57
поделиться
  • 1
    Вы знаете какой-либо надежный способ сделать это с помощью URL-адреса, а не файла? Какие ошибки меня способ найти длину контента URL. Как указано здесь, кажется, что нет способа узнать размер потока, если мы используем сжатие gzip. [Д0] android-developers.blogspot.fr/2011/09/… – Snicolas 11 October 2012 в 14:04
  • 2
    Ответ Адамски работает, но есть небольшая ошибка. Метод overridden read (byte [] b) вызывает метод read (byte [] b, int off, int len) через суперкласс. Поэтому updateProgress (long numBytesRead) вызывается дважды для каждого действия чтения, и вы получаете numBytesRead, который в два раза превышает размер файла после того, как весь файл был прочитан. Невыполнение метода read (byte [] b) решает проблему. – WillamS 24 February 2014 в 17:21
  • 3
    (Разве этот комментарий не должен быть прикреплен к этому ответу?) – Kevin Bourrillion 17 March 2014 в 18:19

Чтобы выполнить ответ, заданный @Kevin Bourillion, он также может быть применен к сетевому контенту, используя этот метод (который предотвращает чтение потока дважды: один для размера и один для контента):

        final HttpURLConnection httpURLConnection = (HttpURLConnection) new URL( url ).openConnection();
        InputSupplier< InputStream > supplier = new InputSupplier< InputStream >() {

            public InputStream getInput() throws IOException {
                return httpURLConnection.getInputStream();
            }
        };
        long total = httpURLConnection.getContentLength();
        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ByteStreams.readBytes( supplier, new ProgressByteProcessor( bos, total ) );

Где ProgressByteProcessor является внутренним классом:

public class ProgressByteProcessor implements ByteProcessor< Void > {

    private OutputStream bos;
    private long progress;
    private long total;

    public ProgressByteProcessor( OutputStream bos, long total ) {
        this.bos = bos;
        this.total = total;
    }

    public boolean processBytes( byte[] buffer, int offset, int length ) throws IOException {
        bos.write( buffer, offset, length );
        progress += length - offset;
        publishProgress( (float) progress / total );
        return true;
    }

    public Void getResult() {
        return null;
    }
}
0
ответ дан Snicolas 18 August 2018 в 21:57
поделиться

Ответ Адамски работает, но есть небольшая ошибка. Переопределенный метод read(byte[] b) вызывает метод read(byte[] b, int off, int len) через суперкласс. Таким образом, updateProgress(long numBytesRead) вызывается дважды для каждого действия чтения, и вы получаете numBytesRead, который в два раза больше размера файла после того, как весь файл был прочитан.

Не отменяет метод read(byte[] b), решает проблему.

4
ответ дан zessx 18 August 2018 в 21:57
поделиться
  • 1
    Это должен быть комментарий ответа @Adamski, а не ответ сам по себе, по крайней мере, если вы не поместите исправленный код в свой ответ. – PhoneixS 24 February 2014 в 17:10
Другие вопросы по тегам:

Похожие вопросы: