如何获取读取文件的进度

时间:2012-11-10 17:12:52

标签: java file progress

我正在尝试从我的应用程序中的文件中读取一个大对象。由于这可能需要一些时间,我想以某种方式将文件的读取与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);
}
}

3 个答案:

答案 0 :(得分:1)

如果是我,我不会乱用重写FileInputStream。我认为decorator可能适合这里。我们的想法是创建一个传递给ObjectInputStream的装饰器输入流。装饰器负责更新读取的进度,然后委托实际的输入流。

也许最简单的解决方案是使用Apache CountingInputStream中的commons-io。基本步骤是:

  • 创建CountingInputStream的子类作为地图加载器的非静态内部类
  • 覆盖afterRead方法。调用super.afterRead,然后发布更新后的状态
  • 将新装饰器输入流的实例传递给输出流,将文件输入流传递给装饰器的构造函数

答案 1 :(得分:0)

使用RandomAccessFile,您可以调用getFilePointer()来了解已读取的字节数。

耗时的操作可以在后台线程中执行,请记住使用SwingUtilities.invokeLater()在后台任务和GUI线程之间进行通信。

答案 2 :(得分:0)

如果您考虑覆盖read()中的FileInputStream,那么您可以合理地考虑使用自己的包装 InputStream类接受进度监控打回来。但是,您会发现它并不像实现read()那么容易,因为对每个字节进行方法调用效率非常低。相反,您需要处理read(byte[], int, int),这需要更多参与。