Java中PrintStream.println()无法输出至文件的问题求助
递归方法中错误日志无法写入文件的问题解决
问题根源分析
你的核心问题出在递归调用时重复创建输出流/错误队列:
- 初始代码中,每次递归调用
getStockData都会新建PrintStream实例,且try-with-resources会在递归方法结束时关闭流。默认的PrintStream构造会直接覆盖目标文件,导致父方法写入的内容被子方法的新流覆盖,最终文件仅保留最外层方法的输出(若无则为空)。 - 修改后的代码虽在当前方法内缓存错误,但递归调用的子方法会创建独立的
errors队列和PrintStream,子方法收集的错误无法汇总到父方法队列,且子方法的流仍会覆盖文件,导致最终文件为空。
解决方案
方案1:共用同一个PrintStream(推荐)
将输出流作为参数传入递归方法,确保所有层级的错误都写入同一个流:
public static LinkedQueue<Stock> getStockData(LinkedQueue<Stock> stockQueue, String startPath, PrintStream recordErrors) throws Exception { File dir = new File(getValidDirectory(startPath)); for (File name : dir.listFiles()) { if (name.isDirectory()) { // 递归时传入同一个输出流 getStockData(stockQueue, name.getPath(), recordErrors); } else if (name.canRead()) { Scanner readFile = new Scanner(name); readFile.nextLine(); while (readFile.hasNext()) { String line = readFile.nextLine(); String[] lineArray = line.split(",+"); if (lineArray.length == 8) { try { Stock stock = new Stock(name.getName().replaceAll("_+(.*)", "")); stock.fromRecord(lineArray); stockQueue.enqueue(stock); } catch (Exception ex) { recordErrors.println(line + " ERROR: " + ex.getMessage()); System.err.println(line + " ERROR: " + ex.getMessage()); recordErrors.flush(); // 主动刷新确保内容写入磁盘 } } else { recordErrors.println(line + " ERROR: Invalid record length."); System.err.println(line + " ERROR: Invalid record length."); recordErrors.flush(); } } readFile.close(); } } return stockQueue; } // 调用入口 public static void main(String[] args) { try (PrintStream recordErrors = new PrintStream(new File("EODdataERRORS.txt"))) { LinkedQueue<Stock> queue = new LinkedQueue<>(); getStockData(queue, "你的起始路径", recordErrors); } catch (Exception e) { System.err.println(e.getMessage()); } }
方案2:统一缓存错误后写入
将错误队列作为参数传递,所有递归层级的错误汇总到同一个队列,最后统一写入文件:
public static LinkedQueue<Stock> getStockData(LinkedQueue<Stock> stockQueue, String startPath, LinkedQueue<String> errors) throws Exception { File dir = new File(getValidDirectory(startPath)); for (File name : dir.listFiles()) { if (name.isDirectory()) { getStockData(stockQueue, name.getPath(), errors); } else if (name.canRead()) { Scanner readFile = new Scanner(name); readFile.nextLine(); while (readFile.hasNext()) { String line = readFile.nextLine(); String[] lineArray = line.split(",+"); if (lineArray.length == 8) { try { Stock stock = new Stock(name.getName().replaceAll("_+(.*)", "")); stock.fromRecord(lineArray); stockQueue.enqueue(stock); } catch (Exception ex) { errors.add(line + " ERROR: " + ex.getMessage()); System.err.println(line + " ERROR: " + ex.getMessage()); } } else { errors.add(line + " ERROR: Invalid record length."); System.err.println(line + " ERROR: Invalid record length."); } } readFile.close(); } } return stockQueue; } // 调用入口 public static void main(String[] args) { LinkedQueue<Stock> stockQueue = new LinkedQueue<>(); LinkedQueue<String> errors = new LinkedQueue<>(); try { getStockData(stockQueue, "你的起始路径", errors); // 统一写入错误文件 try (PrintStream recordErrors = new PrintStream(new File("EODdataERRORS.txt"))) { while (!errors.isEmpty()) { recordErrors.println(errors.remove()); } } } catch (Exception e) { System.err.println(e.getMessage()); } }
注意事项
- 禁止在递归方法内重复创建文件输出流,否则会导致文件覆盖或流提前关闭。
- 使用try-with-resources管理流时,确保流的生命周期覆盖所有写入操作。
- 写入后调用
flush()可避免缓存导致的内容延迟写入或丢失。
内容的提问来源于stack exchange,提问作者James C
相关产品推荐
相关产品推荐

