-1

I am trying to write a method which recursively gathers data from files, and writes erroneous data to an error file. See code block:

public static LinkedQueue<Stock> getStockData(LinkedQueue<Stock> stockQueue, String startPath) throws Exception {
        File dir = new File(getValidDirectory(startPath));
        try (PrintStream recordErrors = new PrintStream(new File("EODdataERRORS.txt"))) {
            for (File name : dir.listFiles()) {
                if (name.isDirectory()) {
                    getStockData(stockQueue, name.getPath());
                }
                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());
                            }
                        }
                        else {
                            recordErrors.println(line + " ERROR: Invalid record length.");
                            System.err.println(line + " ERROR: Invalid record length.");
                        }
                    }
                }
            }
        }
        catch (FileNotFoundException ex) {
            System.err.println("FileNotFoundException. Please ensure the directory is configured properly.");
        }
        return stockQueue;
    }

However, the error file is always blank.

I've tried calling the .flush() and .close() methods. System.err is outputting so I know the code is being run. I've tried instantiating the PrintStream outside of the try-with-resources, no change.

I've tried calling the method at earlier points in the code (i.e. right after instantiation of the printStream, and in the if{} block) and it does output to the error file. It's only within the catch{} and else{} blocks (where I actually need it to work) that it refuses to print anything. I've also tried storing the error data and using a loop after the blocks to print the data and it still won't work. See code block:

public static LinkedQueue<Stock> getStockData(LinkedQueue<Stock> stockQueue, String startPath) throws Exception {
        File dir = new File(getValidDirectory(startPath));
        LinkedQueue errors = new LinkedQueue();
        try (PrintStream recordErrors = new PrintStream(new File("EODdataERRORS.txt"))) {
            for (File name : dir.listFiles()) {
                if (name.isDirectory()) {
                    getStockData(stockQueue, name.getPath());
                }
                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.enqueue(line + " ERROR: " + ex.getMessage());
                                System.err.println(line + " ERROR: " + ex.getMessage());
                            }
                        }
                        else {
                            errors.enqueue(line + " ERROR: Invalid record length.");
                            System.err.println(line + " ERROR: Invalid record length.");
                        }
                    }
                }
            }
            while (!errors.isEmpty()) {
                recordErrors.println(errors.dequeue());
            }
        }
        catch (FileNotFoundException ex) {
            System.err.println("FileNotFoundException. Please ensure the directory is configured properly.");
        }
        return stockQueue;
    }

Edit

Code has been edited to show instantiation of the PrintStream only once. The error persists. I am sorry there is no Repex, I cannot recreate this error except for in this specific case.

halfer
  • 19,824
  • 17
  • 99
  • 186
James C
  • 11
  • 3
  • Please create a [**Minimal** reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) – ATP Nov 20 '22 at 10:54
  • I am having trouble writing a minimal reproductible example. When I try to recreate the exact conditions on a smaller scale, it works exactly as intended – James C Nov 20 '22 at 11:36
  • Nothing in this code would lead to the problem you observe. No, `println` is not broken in a language used by millions of people daily. Hence, it's hard to help you here. Some tips to aid in your debugging: Print the absolute path of that file, perhaps it _is_ being written, just not in the place you thought. Do you call `System.exit` somewhere _within_ this loop? Because that would cause the printstream _not_ to get cleaned up - don't do that. – rzwitserloot Nov 20 '22 at 11:44
  • Please trim your code to make it easier to find your problem. Follow these guidelines to create a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – Community Nov 20 '22 at 12:09
  • @JamesC Your code does `PrintStream recordErrors = new PrintStream(new File("EODdataERRORS.txt"))` for every single file which is not a directory. Shouldn't you do that just once at the start of `getStockData()`, before you process anything? – skomisa Nov 20 '22 at 18:20
  • @skomisa I have tried both ways, no change. Thanks – James C Nov 20 '22 at 22:00
  • @JamesC Regardless, instantiating the `PrintStream()` as shown in your code is simply wrong, because ([as the Javadoc for PrintStream states](https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/io/PrintStream.html#%3Cinit%3E(java.io.File))): _"**If the file exists, then it will be truncated to zero size**"_. So as your code processes each file within a directory, it repeatedly discards anything that has already been written to EODdataERRORS.txt! Update your code to show `recordErrors` only being instantiated once. Otherwise your question should be deleted. – skomisa Nov 20 '22 at 23:31
  • @skomisa The edit has been made, the error persists. Thank you – James C Nov 22 '22 at 04:11

1 Answers1

1

I have solved the issue. I'm not really sure what the issue was, but it appears to have something to do with the PrintStream being instantiated in a method other than the main{} method. This would also explain why I was unable to recreate this error, try as I might.

As such, I've solved it by simply storing the errors in a list and printing them in the main{} method.

public static void getStockData(LinkedQueue<Stock> stockQueue, LinkedQueue<String> errorQueue, String startPath) {
        File dir = new File(getValidDirectory(startPath));
        try {
            for (File name : dir.listFiles()) {
                if (name.isDirectory()) {
                    getStockData(stockQueue, errorQueue, name.getPath());
                }
                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) {
                                errorQueue.enqueue(line + "; ERROR: " + ex.getMessage());
                                System.err.println(line + "; ERROR: " + ex.getMessage());
                            }
                        }
                        else {
                            errorQueue.enqueue(line + "; ERROR: Invalid record length.");
                            System.err.println(line + "; ERROR: Invalid record length.");
                        }
                    }
                }
            }
        }
        catch (FileNotFoundException ex) {
            System.err.println("FileNotFoundException. Please ensure the directory is configured properly.");
        }
    }

This has the downside of taking up more memory, but I see no other way to get this to work the way I want it to. Thanks for the help!

James C
  • 11
  • 3