1

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

3 回答 3

1

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

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

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

使用RandomAccessFile您可以调用getFilePointer()来了解读取了多少字节。

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

于 2012-11-10T17:18:41.773 回答
0

如果您正在考虑覆盖read()in FileInputStream,那么您可以合理地考虑制作自己的包装 InputStream类来接受进度监视器回调。但是,您会发现它并不像实现那么容易,read()因为为每个字节花费一个方法调用是非常低效的。相反,您需要处理read(byte[], int, int),这涉及更多。

于 2012-11-10T17:55:46.680 回答