0

I am passing in a CSVPrinter printer in a method and internally in a loop I am invoking printRecord method. Below is the snippet of the method.

private void printToCsv(String currentDate, LinkedHashMap<String, LinkedList<CMonthlyStats>> contracts, CSVPrinter printer){
    List<String> activeContracts = ContractMonthlyStatsReader.getListOfActiveContracts(currentDate, contrs);
    for (String activeContract: activeContracts){

     CMonthlyStatsR report =  getCMonthlyStatsR(currentDate, activeContr, contracts.get(activeContr));
      try {
        printer.printRecord(
            report.getAID(),
            report.getMD(),

            report.getAL(), report.getEL(),
            ReportUtil.getMatchValue(),

            report.getAFL(), report.getEFL(),
            ReportUtil.getMatchValue(),

            report.getAPF(), report.getEPF(),
            ReportUtil.getMatchValue()
        );
        printer.flush();
      }

      catch (IOException e) {
        e.printStackTrace();
      }

    }
  }

The printer is being initialized by another method in the main method in the following way:

public void Main(){
.....
    CSVFormat format = getformatWithHeaders();
    final CSVPrinter printer = getCSVPrinter(format);
.....
    for(String string: Strings){
       .......
       printToCsv(currentDate, contrs, printer);

       .......
    }
}

Snippet of getCSVPrinter(format) method:

private CSVPrinter getCSVPrinter(CSVFormat format){
    try (final FileWriter newWriter = new FileWriter(System.getProperty("output.file"))){
      try(final CSVPrinter printer = new CSVPrinter(newWriter, format)){
        return printer;
      }
    }
    catch (IOException e){
      e.printStackTrace();
    }
    return null;
  }

The Header prints to the output file, however everytime a record is trying to be print I am getting java.io.IOException: Stream closed. Handling IOs have always been a nightmare for me. Please help!

The CSVPrinter is from org.apache.commons.csv

sophist_pt
  • 329
  • 1
  • 8
  • 19

2 Answers2

2

You use the try-with-resources feature in your getCSVPrinter-method. It closes the stream automatically if you leave this block.

try(final CSVPrinter printer = new CSVPrinter(newWriter, format)){
  return printer;
}

One solution is to remove the try-block and just return new CSVPrinter(newWriter, format). But then you have to close the stream aftre your operations yourself.

Another solution would be to do all your stream-handling inside the try-with-resources-block.


Here is an example which uses the consumer interface to write into CsvPrinter in the try-with-resources-block.

public void Main(){
    .....
    CSVFormat format = getformatWithHeaders();
    .....
    for(String string: Strings){
       .......
       printToCsv(currentDate, contrs, format);
       .......
    }
}

private void printToCsv(String currentDate, LinkedHashMap<String, LinkedList<CMonthlyStats>> contracts, CSVFormat format){
    List<String> activeContracts = ContractMonthlyStatsReader.getListOfActiveContracts(currentDate, contrs);
    for (String activeContract: activeContracts){

     CMonthlyStatsR report =  getCMonthlyStatsR(currentDate, activeContr, contracts.get(activeContr));
     printToCSV(format, printer -> {
         try {
            printer.printRecord(
                report.getAID(),
                report.getMD(),

                report.getAL(), report.getEL(),
                ReportUtil.getMatchValue(),

                report.getAFL(), report.getEFL(),
                ReportUtil.getMatchValue(),

                report.getAPF(), report.getEPF(),
                ReportUtil.getMatchValue()
            );
            printer.flush();
          }

          catch (IOException e) {
            e.printStackTrace();
          }
        });
    }
}

private void printToCSV(CSVFormat format, Consumer<CSVPrinter> consumer){
    try (final FileWriter newWriter = new FileWriter(System.getProperty("output.file"))){
      try(final CSVPrinter printer = new CSVPrinter(newWriter, format)){
        consumer.accept(printer);
      }
    }
    catch (IOException e){
      e.printStackTrace();
    }
}
Benjamin Schüller
  • 2,104
  • 1
  • 17
  • 29
1

The error you're having is a missinterpretation of the Try-with-resources-statement.

in your try blocks you're opening a FileWriter and then a CSVPrinter:

try (final FileWriter newWriter = new FileWriter(System.getProperty("output.file"))){
  try(final CSVPrinter printer = new CSVPrinter(newWriter, format)){
    return printer;
  }
}
catch (IOException e){
  e.printStackTrace();
}

but when you return the printer it already gets closed, because the try-with-resources-statement is closed.

So if you want to return the printer, then dont use try with resources

Have a look at this question for more information: https://stackoverflow.com/a/22947904/5515060

Lino
  • 19,604
  • 6
  • 47
  • 65
  • I could totally do that. But how would I ensure that the stream gets closed. Because the writer would not be accessible in the main scope. I was thinking maybe I could just try to close the printer in the finally block in the main method's scope. Would this ensure the proper closing of the stream? – sophist_pt Oct 16 '17 at 11:38
  • @sophist_pt the easiest way is to remove the whole `getCSVPrinter()` method and just paste your code to where it is used. Else you get a lot of work around, which just seems unnecessary – Lino Oct 16 '17 at 11:40