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

Java中PrintStream.println()无法输出至文件的问题求助

递归方法中错误日志无法写入文件的问题解决

问题根源分析

你的核心问题出在递归调用时重复创建输出流/错误队列:

  1. 初始代码中,每次递归调用getStockData都会新建PrintStream实例,且try-with-resources会在递归方法结束时关闭流。默认的PrintStream构造会直接覆盖目标文件,导致父方法写入的内容被子方法的新流覆盖,最终文件仅保留最外层方法的输出(若无则为空)。
  2. 修改后的代码虽在当前方法内缓存错误,但递归调用的子方法会创建独立的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 07:25:33