如何在main()方法中复用loadMap的BufferedReader,避免重复创建?
复用BufferedReader解决重复文件读取的问题
嘿,这个问题其实很好解决——我们只需要通过重载loadMap方法的方式,让它支持外部传入已有的BufferedReader,这样就能避免重复打开文件、重复创建流的问题。同时还要注意修复原代码里的资源泄漏问题,以及处理流位置重置的细节。
具体修改步骤:
重载
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; } }修改原
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; } }在
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
相关产品推荐
相关产品推荐

