You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在main()方法中复用loadMap的BufferedReader,避免重复创建?

复用BufferedReader解决重复文件读取的问题

嘿,这个问题其实很好解决——我们只需要通过重载loadMap方法的方式,让它支持外部传入已有的BufferedReader,这样就能避免重复打开文件、重复创建流的问题。同时还要注意修复原代码里的资源泄漏问题,以及处理流位置重置的细节。

具体修改步骤:

  1. 重载loadMap方法,支持传入BufferedReader
    把原loadMap(String filename)里的核心读取逻辑抽出来,放到一个接受BufferedReader参数的重载方法里。这个方法不需要处理文件的打开和关闭,因为流是外部传入的,由外部负责管理生命周期。

    // 新增的重载方法:接受外部传入的BufferedReader
    private static Object[] loadMap(BufferedReader bf) {
        Player player = null;
        try {
            String line = bf.readLine();
            int idcap = Integer.parseInt(line);
            Room[] rooms = new Room[idcap];
            for (int i = 0; i < idcap; ++i) {
                line = bf.readLine();
                if (line == null) {
                    return null;
                }
                rooms[i] = new Room(line);
            }
            for (int i = 0; i < idcap; ++i) {
                line = bf.readLine();
                int exitcount=Integer.parseInt(line);
                for (int j=0; j < exitcount; ++j) {
                    line = bf.readLine();
                    if (line == null) {
                        return null;
                    }
                    int pos = line.indexOf(' ');
                    if (pos < 0) {
                        return null;
                    }
                    int target = Integer.parseInt(line.substring(0,pos));
                    String exname = line.substring(pos+1);
                    try {
                        rooms[i].addExit(exname, rooms[target]);
                    } catch (ExitExistsException e) {
                        return null;
                    } catch (NullRoomException e) {
                        return null;
                    }
                }
            }
            for (int i = 0;i<idcap;++i) {
                line = bf.readLine();
                int itemcount = Integer.parseInt(line);
                for (int j = 0; j < itemcount; ++j) {
                    line = bf.readLine();
                    if (line == null) {
                        return null;
                    }
                    Thing t = decodeThing(line, rooms[0]);
                    if (t == null) {
                        return null;
                    }
                    if (t instanceof Player) {
                        player = (Player)t;
                    } else {
                        rooms[i].enter(t);
                    }
                }
            }
            Object[] res = new Object[2];
            res[0] = player;
            res[1] = rooms[0];
            return res;
        } catch (IOException ex) {
            return null;
        } catch (IndexOutOfBoundsException ex) {
            return null;
        } catch (NumberFormatException nfe) {
            return null;
        }
    }
    
  2. 修改原loadMap(String filename)方法,调用重载方法并修复资源泄漏
    原方法里的BufferedReader没有关闭,会造成资源泄漏,现在修改它让它创建流后调用重载方法,并用try-with-resources确保流被正确关闭:

    public static Object[] loadMap(String filename) {
        // 使用try-with-resources自动关闭流,避免资源泄漏
        try (BufferedReader bf = new BufferedReader(new FileReader(filename))) {
            return loadMap(bf); // 调用重载的方法
        } catch (IOException ex) {
            return null;
        }
    }
    
  3. 在main方法中复用流并处理流位置重置
    你在main里已经读取了一遍文件到names列表,这时候流的指针已经到了文件末尾,直接传给loadMap会读不到内容。所以需要先标记流的起始位置,读完names后重置回标记位置:

    public static void main(String args[]) {
        if (args.length < 1) {
            System.err.println("Usage:\n" +"java CrawlGui mapname");
            System.exit(1);
        }
        String filename = args[0];
        List<String> names=new LinkedList<String>();
        try (BufferedReader reader = new BufferedReader(new FileReader(new File(filename)))) {
            // 标记流的起始位置,参数是标记位置能容纳的最大字符数
            reader.mark(Integer.MAX_VALUE);
            
            // 读取names列表
            String line;
            while ((line = reader.readLine()) != null) {
                names.add(line);
            }
            System.out.println(names);
            
            // 重置流到之前标记的起始位置
            reader.reset();
            
            // 复用已有的reader调用loadMap
            Object[] mapData = MapIO.loadMap(reader);
            System.out.println(mapData[0]);
            System.out.println(mapData[1]);
        } catch (IOException e) {
            e.printStackTrace();
        }
        launch(args);
    }
    

关键细节说明:

  • 流的生命周期管理:外部传入的流由调用方(这里是main方法)负责关闭,所以我们用try-with-resources包裹reader,确保无论是否发生异常,流都会被正确关闭。
  • 流位置重置:mark()和reset()是BufferedReader的特性,需要确保标记的字符数足够覆盖整个文件内容,这里用Integer.MAX_VALUE是比较稳妥的方式(只要文件大小不超过内存限制)。
  • 兼容性:原有的loadMap(String filename)方法保持功能不变,其他地方的调用不需要修改,只在需要复用流的地方调用重载方法即可。

内容的提问来源于stack exchange,提问作者Ninja

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:19:00