Dav*_*les 10 java inputstream java-io
所以,我正在将文件数据提供给需要a的API,Reader我想要一种报告进度的方法.
看起来应该直截了当地编写一个FilterInputStream包装的实现,FileInputStream跟踪读取的字节数与总文件大小,并触发一些事件(或调用某些update()方法)来报告小数进度.
(或者,它可以报告绝对字节读取,而其他人可以进行数学计算 - 在其他流式传输情况下可能更常用.)
我知道我以前见过这个,我甚至可能以前做过,但我找不到代码,而且我很懒.有没有人得到它?或者有人可以提出更好的方法吗?
一年(有点)之后......
我在下面根据Adamski的答案实施了一个解决方案,并且它有效,但经过几个月的使用后我不推荐它.当您有大量更新时,解雇/处理不必要的进度事件会产生巨大的成本.基本的计数机制很好,但是对于那些关心进展调查的人来说要好得多,而不是把它推到他们身上.
(如果你知道总的大小,你可以尝试每隔1%的变化或者其他任何事情来发射一个事件,但这不值得麻烦.通常,你没有.)
Ada*_*ski 12
这是一个相当基本的实现,PropertyChangeEvent在读取其他字节时触发.一些警告:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
番石榴的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);
}
Run Code Online (Sandbox Code Playgroud)
这可能看起来像很多代码,但我相信它是你逃脱的最少.(注意这个问题的其他答案并没有提供完整的代码示例,因此很难以这种方式对它们进行比较.)
Adamski 的答案有效,但有一个小错误。被覆盖read(byte[] b)的read(byte[] b, int off, int len)方法通过超类调用方法。
SoupdateProgress(long numBytesRead)为每个读取操作调用两次,并且numBytesRead在读取整个文件后最终得到的文件大小是文件大小的两倍。
不覆盖read(byte[] b)方法可以解决问题。
| 归档时间: |
|
| 查看次数: |
10694 次 |
| 最近记录: |