一.问题,CSVWriter生成文件时使用writer.writeRecord();方法保存的文件末尾多一个空行,效果图如下:
目标结果:(去掉末尾空行)
二.关键代码如下(修改前代码):
1 /** 2 * 生成CSV文件 3 * @param filePath 文件保存路径,例如:D:/temp/test.csv 4 * @param headerBeans 实体对象集合 5 * @param detailBeans 实体对象集合 6 * @param trailerBeans 实体对象集合 7 * @param <T> 8 */ 9 public static <T> void createFile(String filePath, List<T> headerBeans, List<T> detailBeans, List<T> trailerBeans) { 10 CsvWriter writer = null; 11 try { 12 // 创建文件对象 13 File file = createFile(filePath); 14 // 生成文件 15 writer = new CsvWriter(filePath, ',', Charset.forName("GBK")); 16 // 获取内容 17 List<String[]> contents = new ArrayList<>(); 18 List<String[]> headerContents = getStringArrayFromBean(headerBeans); 19 List<String[]> detailContents = getStringArrayFromBean(detailBeans); 20 List<String[]> trailerContents = getStringArrayFromBean(trailerBeans); 21 contents.addAll(headerContents); 22 contents.addAll(detailContents); 23 contents.addAll(trailerContents); 24 // 写入内容 25 for (String[] each : contents) { 26 writer.writeRecord(each); 27 } 28 } catch (Exception e) { 29 LOGGER.error("生成CSV文件失败", e); 30 } finally { 31 if (writer != null) { 32 writer.close(); 33 } 34 } 35 }
输出文件就在第26行,writer.writeRecord(each);点进去跳到import com.csvreader.CsvWriter;这个包中,如下截图(序号为程序执行调用顺序):
可以看到执行到endRecord()方法时,总是会执行else中的内容,因为useCustomRecordDeliniter定义的为false...(就是这导致了末尾多一空行)
三.解决问题:
.class文件又不能改, 在这里是换了一种写法 ( 由原来的CSVWriter的writeRecord() 改为用PrintWriter的pw.write() )
1 /** 2 * 生成CSV文件 3 * @param filePath 文件保存路径,例如:D:/temp/test.csv 4 * @param headerBeans 实体对象集合 5 * @param detailBeans 实体对象集合 6 * @param trailerBeans 实体对象集合 7 * @param <T> 8 */ 9 public static <T> void createFile(String filePath, List<T> headerBeans, List<T> detailBeans, List<T> trailerBeans) { 10 CsvWriter writer = null; 11 try { 12 // 创建文件对象 13 File file = createFile(filePath); 14 // 生成文件 15 writer = new CsvWriter(filePath, ',', Charset.forName("GBK")); 16 // 获取内容 17 List<String[]> contents = new ArrayList<>(); 18 List<String[]> headerContents = getStringArrayFromBean(headerBeans); 19 List<String[]> detailContents = getStringArrayFromBean(detailBeans); 20 List<String[]> trailerContents = getStringArrayFromBean(trailerBeans); 21 contents.addAll(headerContents); 22 contents.addAll(detailContents); 23 contents.addAll(trailerContents); 24 // 重组内容 25 String result = ""; 26 for (String[] each : contents) { 27 for (String s : each){ 28 writer.writeRecord(each); 29 result += s ; 30 result += ","; 31 } 32 result = result.substring(0,result.length()-1); 33 result += "\r\n"; 34 } 35 result = result.substring(0,result.length()-2); 36 37 writeFileContent(filePath,result);//写入 38 } catch (Exception e) { 39 LOGGER.error("生成CSV文件失败", e); 40 } finally { 41 if (writer != null) { 42 writer.close(); 43 } 44 } 45 }
调用的writeFileContent()方法如下:
/** * 向文件中写入内容 * * @param filepath 文件路径与名称 * @param newstr 写入的内容 * @return * @throws IOException */ public static boolean writeFileContent(String filepath, String newstr) throws IOException { Boolean bool = false; String temp = ""; FileInputStream fis = null; InputStreamReader isr = null; BufferedReader br = null; FileOutputStream fos = null; PrintWriter pw = null; try { /* File file = new File(filepath);*///文件路径(包括文件名称) //将文件读入输入流 fis = new FileInputStream(filepath); isr = new InputStreamReader(fis); br = new BufferedReader(isr); // StringBuffer buffer = new StringBuffer(); // //文件原有内容 // for (int i = 0; (temp = br.readLine()) != null; i++) { // buffer.append(temp); // // 行与行之间的分隔符 相当于“\n” // buffer = buffer.append(System.getProperty("line.separator")); // } // buffer.append(newstr); fos = new FileOutputStream(filepath); pw = new PrintWriter(fos); pw.write(newstr.toCharArray()); pw.flush(); bool = true; } catch (Exception e) { // TODO: handle exception e.printStackTrace(); throw e; } finally { //不要忘记关闭 if (pw != null) { pw.close(); } if (fos != null) { fos.close(); } if (br != null) { br.close(); } if (isr != null) { isr.close(); } if (fis != null) { fis.close(); } } return bool; }
贴上完整的新utils留个备份:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 package com.sp.ppms.console.finance.CSV; 2 3 import java.io.*; 4 import java.lang.reflect.Field; 5 import java.lang.reflect.Method; 6 import java.nio.charset.Charset; 7 import java.util.ArrayList; 8 import java.util.Collections; 9 import java.util.HashMap; 10 import java.util.List; 11 import java.util.Map; 12 import java.util.Map.Entry; 13 import org.apache.commons.lang3.StringUtils; 14 import org.apache.log4j.Logger; 15 import org.springframework.util.ReflectionUtils; 16 import com.csvreader.CsvReader; 17 import com.csvreader.CsvWriter; 18 19 /** 20 * CSV工具类 21 */ 22 public class CSVUtil { 23 /** 24 * 日志对象 25 **/ 26 private static final Logger