我正在尝试从我的应用程序中的文件中读取一个大对象。由于这可能需要一些时间,我想以某种方式将文件的读取与JProgressBar连接起来。有没有简单的方法来查找阅读文件的进度? (加载本身是在swingworker线程中完成的,因此更新进度条应该不是问题。)我一直在考虑覆盖FileInputStream中的readByte()方法以返回排序的进度值,但这看起来很狡猾办法。关于如何实现这一点的任何建议都非常受欢迎。
以下是阅读文件的代码:
public class MapLoader extends SwingWorker<Void, Integer> {
String path;
WorldMap map;
public void load(String mapName) {
this.path = Game.MAP_DIR + mapName + ".map";
this.execute();
}
public WorldMap getMap() {
return map;
}
@Override
protected Void doInBackground() throws Exception {
File f = new File(path);
if (! f.exists())
throw new IllegalArgumentException(path + " is not a valid map name.");
try {
FileInputStream fs = new FileInputStream(f);
ObjectInputStream os = new ObjectInputStream(fs);
map = (WorldMap) os.readObject();
os.close();
fs.close();
} catch (IOException | ClassCastException | ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void done() {
firePropertyChange("map", null, map);
}
}
答案 0 :(得分:1)
如果是我,我不会乱用重写FileInputStream。我认为decorator可能适合这里。我们的想法是创建一个传递给ObjectInputStream的装饰器输入流。装饰器负责更新读取的进度,然后委托实际的输入流。
也许最简单的解决方案是使用Apache CountingInputStream中的commons-io。基本步骤是:
afterRead
方法。调用super.afterRead,然后发布更新后的状态答案 1 :(得分:0)
使用RandomAccessFile,您可以调用getFilePointer()来了解已读取的字节数。
耗时的操作可以在后台线程中执行,请记住使用SwingUtilities.invokeLater()在后台任务和GUI线程之间进行通信。
答案 2 :(得分:0)
如果您考虑覆盖read()
中的FileInputStream
,那么您可以合理地考虑使用自己的包装 InputStream
类接受进度监控打回来。但是,您会发现它并不像实现read()
那么容易,因为对每个字节进行方法调用效率非常低。相反,您需要处理read(byte[], int, int)
,这需要更多参与。