SuperCSV的输出难以理解?

时间:2012-09-10 19:27:13

标签: java spring csv format supercsv

我有一个为Spring控制器创建的实用程序类,可以调用使用SuperCSV库(http://supercsv.sourceforge.net/)从bean集合生成CSV

实用程序类非常基本:

public static void export2CSV(HttpServletResponse response,
        String[] header, String filePrefix, List<? extends Object> dataObjs) {
    try{
        response.setContentType("text/csv;charset=utf-8"); 
        response.setHeader("Content-Disposition","attachment; filename="+filePrefix+"_Data.csv");

        OutputStream fout= response.getOutputStream();  
        OutputStream bos = new BufferedOutputStream(fout);   
        OutputStreamWriter outputwriter = new OutputStreamWriter(bos); 

        ICsvBeanWriter writer = new CsvBeanWriter(outputwriter, CsvPreference.EXCEL_PREFERENCE);

        // the actual writing
        writer.writeHeader(header);

        for(Object anObj : dataObjs){
            writer.write(anObj, header);                                
        }
    }catch (Exception e){
        e.printStackTrace();
    }
};

问题是,我从这个操作中得到了不同的行为,我不知道为什么。当我从一个控制器调用它时(我们称之为'A'),我得到了预期的数据输出。

当我从另一个控制器('B')调用它时,我得到一小部分无法识别的二进制数据,这些数据无法通过OO Calc打开。在Notepad ++中打开它会产生一条难以理解的乱码行,我只能假设读者试图向我展示二进制流。

控制器'A'调用(有效的)

@RequestMapping(value="/getFullReqData.html", method = RequestMethod.GET)
public void getFullData(HttpSession session, HttpServletRequest request, HttpServletResponse response) throws IOException{
    logger.info("INFO:  ******************************Received request for full Req data dump");
    String projName=  (String)session.getAttribute("currentProject");
    int projectID = ProjectService.getProjectID(projName);
    List<Requirement> allRecords = reqService.getFullDataSet(projectID);

      final String[] header = new String[] { 
              "ColumnA", 
              "ColumnB",                  
              "ColumnC",
              "ColumnD",
              "ColumnE"
              };

      CSVExporter.export2CSV(response, header, projName+"_reqs_", allRecords);


};

...这里是Controller'B'调用(失败的那个):

@RequestMapping(value="/getFullTCData.html", method = RequestMethod.GET)
public void getFullData(HttpSession session, HttpServletRequest request, HttpServletResponse response) throws IOException{
    logger.info("INFO:  Received request for full TCD data dump");
    String projName=  (String)session.getAttribute("currentProject");
    int projectID = ProjectService.getProjectID(projName);
    List<TestCase> allRecords = testService.getFullTestCaseList(projectID);

    final String[] header = new String[] { 
            "ColumnW", 
            "ColumnX",
            "ColumnY",                
            "ColumnZ"
         };

    CSVExporter.export2CSV(response, header, projName+"_tcs_", allRecords);
}

观察:

  • 我首先调用哪个控制器是无关紧要的。 'A'总是有效,'B'总是产生胡言乱语
  • 对此函数的两次调用都有一个标题列列表,这些列是传入CSVWriter的bean中定义的操作总集的子集
  • 简单的异常printStackTrace正在检测bean的反射字段何时与定义不匹配(即,无法找到get()以编程方式获取值)建议所有列/变量匹配成功。
  • 在调试器中,我已经验证了writer.write(Object,header)调用是根据传递的对象数量达到了预期的次数,并且这些对象具有预期的数据

非常感谢任何建议或见解。我真的很难过如何更好地隔离这个问题......

1 个答案:

答案 0 :(得分:2)

你没有关闭作家。此外,CsvBeanWriter会将编写器包装在BufferedWriter中,因此您可以简化outputwriter

public static void export2CSV(HttpServletResponse response,
        String[] header, String filePrefix, List<? extends Object> dataObjs) {
    ICsvBeanWriter writer;
    try{
        response.setContentType("text/csv;charset=utf-8"); 
        response.setHeader("Content-Disposition",
            "attachment; filename="+filePrefix+"_Data.csv");

        OutputStreamWriter outputwriter = 
            new OutputStreamWriter(response.getOutputStream()); 

        writer = new CsvBeanWriter(outputwriter, CsvPreference.EXCEL_PREFERENCE);

        // the actual writing
        writer.writeHeader(header);

        for(Object anObj : dataObjs){
            writer.write(anObj, header);                                
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            writer.close(); // closes writer and underlying stream
        } catch (Exception e){}
    }
};

Super CSV 2.0.0-beta-1现在出来了!除了添加许多其他功能(包括Maven支持和新的Dozer扩展)之外,CSV编写器现在也公开了flush()方法。