InputStreamまたはReaderラッパーのための進捗報告
-
20-09-2019 - |
質問
なので、私は給餌のファイルデータAPIを取る Reader
, ていただきたいと思いますように報告します。
このようなものを書く FilterInputStream
実施のロッドやルアーを使用することに FileInputStream
, を把読み込むバイト数に対の合計ファイルのサイズや火災など一部のイベント(または、通話があ update()
法)による報告書の端ます。
(もし、この報告書絶対読み込まれたバイトは、他人になりの数学--もより一般的に有用なその他のストリーミングです。)
思いこの前まで行ったことはあって、できるなどのコードとい踏む。でっけ?で誰からよりよいアプローチを考えていますか。
一年およびビット)。
私の実施基づいてソリューションAdamskiの答えを示したが、その後一ヶ月間使用できないのをお勧めします。るときは、多数の更新、焼成/取り扱い不要な進捗イベントとなり巨大なコストです。基本集計機構のですがりに人気の進捗にポうです。
(がわかっている場合は、それを合計サイズお試しいただくことが可能でみ焼成イベント毎>1%に変更または何もないかの問題。"とよばれしないかのどちらかになります。)
解決
こちらはかなり基本的な実装する火災 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;
}
}
他のヒント
グァバ's com.google.common.io
パッケージできます。以下はuncompiled、未審査できます。
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);
}
この場合のように多くのコードだと思いますの少なくともいわれます。注その他の回答がない 完全 コード例では難しいと比較してみてくださいすることができてうれしいです。)
その答えによるAdamski作品が小さくなる場合もありますのオーバーライド read(byte[] b)
メソッドの呼び出しの read(byte[] b, int off, int len)
ソト、スーパークラスです。
なので updateProgress(long numBytesRead)
は回毎に読みで動い numBytesRead
このファイルのサイズ後の合計ファイルを読み込みます。
なをオーバー read(byte[] b)
方法を解決の問題です。
だ建物は、GUIアプリケーションが常にある ProgressMonitorInputStream.であれば、GUIに関わる包装する InputStream
方法について説明していただけまがない-同じ系列は、時間以上を掲載。
の答えを与えるには以下のように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;
}
}