一:主要内容

  • 解决CsvWriter存csv,csv文件打开后中文乱码问题
  • 解决CsvWriter存csv,csv文件最后一行总是多一行空行的问题
  • 解决CsvWriter存csv,csv文件不是第一列的时候,想存入""即空字符串无法存入显示null的问题

二:解决问题前:需要做的事情

因为网上的CsvWrite的jar包导入到我们的工程中是class文件,针对上面的问题是无法修改源码的,但是我们又想用这个工具来操作csv,所以可以在自己的工程中首先pom引用这个jar包

 <dependency>
<groupId>net.sourceforge.javacsv</groupId>
<artifactId>javacsv</artifactId>
<version>2.0</version>
</dependency>

然后我们在自己的工程中创建一个类:CsvWriterExtend来继承CsvWriter,这样我们就能用网上CsvWriter这个jar中的方法,还能基于这个去修改代码,解决上诉的问题

public class CsvWriterExtend extends CsvWriter {}

三:优化解决CsvWriter工具存在的三个问题:中文乱码、末尾行多一行空格(/r)、非第一列空字符串""显示null问题

此处废话不多说,先上CsvWriterExtend类的代码,然后我们在代码中红色标注的地方会有说明,这段用来解决什么问题的,说明一下:CsvWriterExtend代码只是在CsvWriter类的基础上做了一些修改

 /**
* Copyright (C), 2015-2019, XXX有限公司
* FileName: CsvWriterExtend
* Author: yml
* Date: 2019/5/17 15:42
* Description:
* History:
* <author> <time> <version> <desc>
* tester 2019.5.17 1.0.0 优化CsvWriter工具
*/
package com.test.csv.tool; import com.csvreader.CsvWriter; import java.io.*;
import java.nio.charset.Charset; /**
* @创建人 tester
* @创建时间 2019/5/17
* @描述 优化CsvWriter工具,解决了写入csv打开后中文乱码问题,解决了写入csv最后一行有/r换行的问题
*
*/
public class CsvWriterExtend extends CsvWriter {
private PrintWriter outputStream;
private String fileName;
private boolean firstColumn;
private boolean useCustomRecordDelimiter;
private Charset charset;
private CsvWriterExtend.UserSettings userSettings;
private boolean initialized;
private boolean closed;
public static final int ESCAPE_MODE_DOUBLED = 1;
public static final int ESCAPE_MODE_BACKSLASH = 2;
private String sheetFirstName; public CsvWriterExtend(String var1, char var2, Charset var3,String sheetFirstName) {
super(var1,var2,var3);
this.outputStream = null;
this.fileName = null;
this.firstColumn = true;
this.useCustomRecordDelimiter = false;
this.charset = null;
this.userSettings = new CsvWriterExtend.UserSettings();
this.initialized = false;
this.closed = false;
//1:这里加了一个csv表头的第一个名字字段,用来解决第一个问题:中文乱码问题
this.sheetFirstName = sheetFirstName;
if (var1 == null) {
throw new IllegalArgumentException("Parameter fileName can not be null.");
} else if (var3 == null) {
throw new IllegalArgumentException("Parameter charset can not be null.");
} else {
this.fileName = var1;
this.userSettings.Delimiter = var2;
this.charset = var3;
}
} public CsvWriterExtend(Writer var1, char var2) {
super(var1,var2);
this.outputStream = null;
this.fileName = null;
this.firstColumn = true;
this.useCustomRecordDelimiter = false;
this.charset = null;
this.userSettings = new CsvWriterExtend.UserSettings();
this.initialized = false;
this.closed = false;
if (var1 == null) {
throw new IllegalArgumentException("Parameter outputStream can not be null.");
} else {
this.outputStream = new PrintWriter(var1);
this.userSettings.Delimiter = var2;
this.initialized = true;
}
} public CsvWriterExtend(OutputStream var1, char var2, Charset var3) {
this(new OutputStreamWriter(var1, var3), var2);
} public char getDelimiter() {
return this.userSettings.Delimiter;
} public void setDelimiter(char var1) {
this.userSettings.Delimiter = var1;
} public char getRecordDelimiter() {
return this.userSettings.RecordDelimiter;
} public void setRecordDelimiter(char var1) {
this.useCustomRecordDelimiter = true;
this.userSettings.RecordDelimiter = var1;
} public char getTextQualifier() {
return this.userSettings.TextQualifier;
} public void setTextQualifier(char var1) {
this.userSettings.TextQualifier = var1;
} public boolean getUseTextQualifier() {
return this.userSettings.UseTextQualifier;
} public void setUseTextQualifier(boolean var1) {
this.userSettings.UseTextQualifier = var1;
} public int getEscapeMode() {
return this.userSettings.EscapeMode;
} public void setEscapeMode(int var1) {
this.userSettings.EscapeMode = var1;
} public void setComment(char var1) {
this.userSettings.Comment = var1;
} public char getComment() {
return this.userSettings.Comment;
} public boolean getForceQualifier() {
return this.userSettings.ForceQualifier;
} public void setForceQualifier(boolean var1) {
this.userSettings.ForceQualifier = var1;
} public void write(String var1, boolean var2) throws IOException {
this.checkClosed();
this.checkInit();
if (var1 == null) {
var1 = "";
}
//2:这里加了一个判断条件,用来解决第一个问题:中文乱码问题
//加的目的是:如果是写入bom则bom后面不追加逗号,即在bom后面和第一个表头前面,即两者之间不追加逗号,sheetFirstName为第一个表头的名字根据实际传入
if (!this.firstColumn && !var1.contentEquals(sheetFirstName) ){
this.outputStream.write(this.userSettings.Delimiter);
} boolean var3 = this.userSettings.ForceQualifier;
if (!var2 && var1.length() > 0) {
var1 = var1.trim();
} if (!var3 && this.userSettings.UseTextQualifier && (var1.indexOf(this.userSettings.TextQualifier) > -1 || var1.indexOf(this.userSettings.Delimiter) > -1 || !this.useCustomRecordDelimiter && (var1.indexOf(10) > -1 || var1.indexOf(13) > -1) || this.useCustomRecordDelimiter && var1.indexOf(this.userSettings.RecordDelimiter) > -1 || this.firstColumn && var1.length() > 0 && var1.charAt(0) == this.userSettings.Comment || this.firstColumn && var1.length() == 0)) {
var3 = true;
} if (this.userSettings.UseTextQualifier && !var3 && var1.length() > 0 && var2) {
char var4 = var1.charAt(0);
if (var4 == ' ' || var4 == '\t') {
var3 = true;
} if (!var3 && var1.length() > 1) {
char var5 = var1.charAt(var1.length() - 1);
if (var5 == ' ' || var5 == '\t') {
var3 = true;
}
}
}
//3:这里加了一个if语句,是为了解决第三个问题:csv""显示null的问题
if(!this.firstColumn && var1.length()==0){
var3=true;
}
if (var3) {
this.outputStream.write(this.userSettings.TextQualifier);
if (this.userSettings.EscapeMode == 2) {
var1 = replace(var1, "\\", "\\\\");
var1 = replace(var1, "" + this.userSettings.TextQualifier, "\\" + this.userSettings.TextQualifier);
} else {
var1 = replace(var1, "" + this.userSettings.TextQualifier, "" + this.userSettings.TextQualifier + this.userSettings.TextQualifier);
}
} else if (this.userSettings.EscapeMode == 2) {
var1 = replace(var1, "\\", "\\\\");
var1 = replace(var1, "" + this.userSettings.Delimiter, "\\" + this.userSettings.Delimiter);
if (this.useCustomRecordDelimiter) {
var1 = replace(var1, "" + this.userSettings.RecordDelimiter, "\\" + this.userSettings.RecordDelimiter);
} else {
var1 = replace(var1, "\r", "\\\r");
var1 = replace(var1, "\n", "\\\n");
} if (this.firstColumn && var1.length() > 0 && var1.charAt(0) == this.userSettings.Comment) {
if (var1.length() > 1) {
var1 = "\\" + this.userSettings.Comment + var1.substring(1);
} else {
var1 = "\\" + this.userSettings.Comment;
}
}
} this.outputStream.write(var1); if (var3) {
this.outputStream.write(this.userSettings.TextQualifier);
} this.firstColumn = false;
} public void write(String var1) throws IOException {
this.write(var1, false);
} public void writeComment(String var1) throws IOException {
this.checkClosed();
this.checkInit();
this.outputStream.write(this.userSettings.Comment);
this.outputStream.write(var1);
if (this.useCustomRecordDelimiter) {
this.outputStream.write(this.userSettings.RecordDelimiter);
} else {
this.outputStream.println();
} this.firstColumn = true;
} public void writeRecord(String[] var1, boolean var2) throws IOException {
if (var1 != null && var1.length > 0) {
for(int var3 = 0; var3 < var1.length; ++var3) {
this.write(var1[var3], var2);
} this.endRecord();
} } public void writeRecord(String[] var1) throws IOException {
this.writeRecord(var1, false);
} public void writeLastRecord(String[] var1) throws IOException {
this.writeLastRecord(var1, false);
} //4:这里加了两个方法writeLastRecord和endLastRecord,用来解决第二个问题:某尾总是多一行空行的问题
public void writeLastRecord(String[] var1, boolean var2) throws IOException {
if (var1 != null && var1.length > 0) {
for(int var3 = 0; var3 < var1.length; ++var3) {
this.write(var1[var3], var2);
} this.endLastRecord();
} }
public void endLastRecord() throws IOException {
this.checkClosed();
this.checkInit();
if (this.useCustomRecordDelimiter) {
this.outputStream.write(this.userSettings.RecordDelimiter);
} else {//主要在下面这一行,当执行这个方法来结尾的时候是不追加换行符的
this.outputStream.print("");
} this.firstColumn = true;
} public void endRecord() throws IOException {
this.checkClosed();
this.checkInit();
if (this.useCustomRecordDelimiter) {
this.outputStream.write(this.userSettings.RecordDelimiter);
} else {
this.outputStream.println();
} this.firstColumn = true;
} private void checkInit() throws IOException {
if (!this.initialized) {
if (this.fileName != null) {
this.outputStream = new PrintWriter(new OutputStreamWriter(new FileOutputStream(this.fileName), this.charset));
} this.initialized = true;
} } public void flush() {
this.outputStream.flush();
} public void close() {
if (!this.closed) {
this.close(true);
this.closed = true;
} } private void close(boolean var1) {
if (!this.closed) {
if (var1) {
this.charset = null;
} try {
if (this.initialized) {
this.outputStream.close();
}
} catch (Exception var3) {
;
} this.outputStream = null;
this.closed = true;
} } private void checkClosed() throws IOException {
if (this.closed) {
throw new IOException("This instance of the CsvWriter class has already been closed.");
}
} protected void finalize() {
this.close(false);
} public static String replace(String var0, String var1, String var2) {
int var3 = var1.length();
int var4 = var0.indexOf(var1);
if (var4 <= -1) {
return var0;
} else {
StringBuffer var5 = new StringBuffer(); int var6;
for(var6 = 0; var4 != -1; var4 = var0.indexOf(var1, var6)) {
var5.append(var0.substring(var6, var4));
var5.append(var2);
var6 = var4 + var3;
} var5.append(var0.substring(var6));
return var5.toString();
}
} private class UserSettings {
public char TextQualifier = '"';
public boolean UseTextQualifier = true;
public char Delimiter = ',';
public char RecordDelimiter = 0;
public char Comment = '#';
public int EscapeMode = 1;
public boolean ForceQualifier = false; public UserSettings() {
}
} private class Letters {
public static final char LF = '\n';
public static final char CR = '\r';
public static final char QUOTE = '"';
public static final char COMMA = ',';
public static final char SPACE = ' ';
public static final char TAB = '\t';
public static final char POUND = '#';
public static final char BACKSLASH = '\\';
public static final char NULL = '\u0000'; private Letters() {
}
}
}

四:调用写好的CsvWriterExtend类,实现写csv功能

下面给出写csv的方法,如下红色部分是解决上诉三个问题的关键:中文乱码、末尾行多一行空格(/r)、非第一列空字符串""显示null问题

  /**
* 写csv方法
*/
public static <T> void writeCSV(Collection<T> dataset, String csvFilePath, String[] csvHeaders) { try {
//集合长度,和循环次数,当循环到最后一条记录时不在末尾插入换行符
int datasetLength = dataset.size();
int loop=1;
// 定义路径,分隔符,编码d,第一个表头名称
//如果是写入bom则bom后面不追加逗号,即在bom后面和第一个表头前面,即两者之间不追加逗号,sheetFirstName为第一个表头的名字根据实际传入
CsvWriterExtend csvWriter = new CsvWriterExtend(csvFilePath, ',', Charset.forName("UTF-8"),"username"); // 写表头
//如果是写入bom解决文件乱码,则不在bom后面追加,号分隔符
csvWriter.write("\ufeff");
csvWriter.writeRecord(csvHeaders); // 写内容
// 遍历集合
Iterator<T> it = dataset.iterator();
while (it.hasNext()) {
T t = (T) it.next();
//获取类属性
Field[] fields = t.getClass().getDeclaredFields();
String[] csvContent=new String[fields.length];
for (short i = 0; i < fields.length; i++) {
Field field = fields[i];
String fieldName = field.getName();
String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
try {
Class tCls = t.getClass();
Method getMethod = tCls.getMethod(getMethodName,new Class[] {});
Object value = getMethod.invoke(t, new Object[] {});
if (value == null) {
continue;
}
//取值并赋给数组
String textvalue=value.toString();
csvContent[i]=textvalue;
}catch (Exception e) {
e.getStackTrace();
}
}
if(loop!=datasetLength){
//迭代插入记录
csvWriter.writeRecord(csvContent);
}else{
//插入最后一条记录
csvWriter.writeLastRecord(csvContent);
} loop=loop+1;
for(String csvs:csvContent) {
System.out.println("记录数据:" + csvs);
}
} csvWriter.close();
System.out.println("<--------CSV文件写入成功-------->");
} catch (IOException e) {
e.printStackTrace();
}
}

调用csv方法即执行类

 public static void main(String[] args) throws Exception{
//造测试数据
List<DataEntity> data = CreateDataModel.createUserData();
String csvFilePath = "E://data.csv";
//表头名称
//注册用户名、注册密码、登录用户名、登录密码、记住我、邮箱、分类名称、文章标题、文章路径、文章标签、文章内容、评论文章、期望结果
String[] csvHeaders = { "username", "password", "loginusername","loginpassword","remeber","email","cname","title","slug","tags","content","comment","expectresult" };
CreateDataModel.writeCSV(data,csvFilePath,csvHeaders); }

生成csv的效果如图:

四:备注

如果想看更详细的代码,可参考我的github地址,如上csv的生成已全部上传github中,地址如下:

https://github.com/mmkxyu/auto-create-test-data.git

博文均为原创文章,转载请注明出处,感谢!

解决CsvWriter:中文乱码、末尾行多一行空格(/r)、非第一列空字符串""显示null问题的更多相关文章

  1. Ubuntu14.04安装中文输入法以及解决Gedit中文乱码问题[转载]

    转载自:http://www.cnblogs.com/zhcncn/p/4032321.html 写在前面:解决gedit 在txt文件格式出现乱码的问题,在我自己的操作中是需要把系统设置成中文显示环 ...

  2. 如何解决PHP中文乱码问题

    如何解决PHP中文乱码问题 一.解决HTML中中文乱码问题方法    1.在head标签里面加入UTF8编码(国际化编码):UTF-8是没有国家的编码,也就是独立于任何一种语言,任何语言都可以使用的. ...

  3. 解决Eclipse中文乱码 - 技术博客 - 51CTO技术博客 http://hsj69106.blog.51cto.com/1017401/595598/

    解决Eclipse中文乱码 - 技术博客 - 51CTO技术博客  http://hsj69106.blog.51cto.com/1017401/595598/

  4. Ubuntu14.04安装中文输入法以及解决Gedit中文乱码问题

    1 设置中文显示环境 1. 打开System Settings 2. 打开Personal-> Language Support. 会弹出如下对话框,提示你“语言支持没安装完整”. 点击“Rem ...

  5. 解决TortoiseCVS中文乱码

    解决TortoiseCVS中文乱码必备,解决方法: 第一:卸载和TortoiseCVS安装一起安装的CVSNT. 第二:安装本版本CVSNT. CVSNT下载地址:http://down.51cto. ...

  6. springMvc解决json中文乱码

    springMvc解决json中文乱码 springMvc解决json中文乱码,springMvc中文乱码,spring中文乱码 >>>>>>>>> ...

  7. 解决URL中文乱码问题--对中文进行加密、解密处理

    解决URL中文乱码问题--对中文进行加密.解密处理 情景:在资源调度中,首先用户需要选择工作目标,然后跟据选择的工作目标不同而选择不同的账号和代理ip.处理过程如下:点击选择账号,在js中获取工作目标 ...

  8. request.getParameter()及解决数据库中文乱码问题——实习第七天

    今天老师让我们自己做一个小项目,我开始着手于实现这个小项目.途中遇到过几个小问题,在此做个小记录, 相信后期还是会借鉴的. 1,从前台传入数据给后台传入数据,并没有传入成功: 输出的为Null. 当然 ...

  9. Hession集成Spring + maven依赖通讯comm项目 + 解决@ResponseBody中文乱码

    hessian结合spring的demo         hessian的maven依赖: <!-- hessian --> <dependency>         < ...

随机推荐

  1. RabbitMQ入门教程(十):队列声明queueDeclare

    原文:RabbitMQ入门教程(十):队列声明queueDeclare 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https:// ...

  2. .net core 2.2.0 SOAP踩坑

    首先确认下面几个程序集是最新版本: <PackageReference Include="System.ServiceModel.Http" Version="4. ...

  3. KNN-综合应用

    本文代码均来自<机器学习实战> 这里讲了两个例子,datingclass 和 figureclass,用到的都是KNN,要调用这两个例子的话就在代码末尾加datingClassTest() ...

  4. java复习(3)继承下

    一.抽象类 ------------------------------------- 1.抽象定义概述:抽象类时从多个事物中奖共性的,本质的内容抽取出来 例如:狼和狗共性都是犬科,犬科就是抽象出来的 ...

  5. uni-app如何编写底部导航栏

    在pages.json中配置代码如下: { "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocat ...

  6. 【抓包工具】使用Fiddler关于“由于目标计算机积极拒绝,无法连接。”的解决方案

    今天使用Fiddler的时候遇到下面这个问题:在地址栏想打开个一般处理程序,出现连接本机失败的提示,如下图: 而这在我没打开Fiddler的时候是显示正常的. 查看Fiddler,在嗅探 -> ...

  7. apache 部署

    <VirtualHost *:80> ServerAdmin webmaster@dummy-host.localhost DocumentRoot "D:/EmpireServ ...

  8. Big Data(五)关于Hadoop的HA的实践搭建

    JoinNode 分布在node01,node02,node03 1.停止之前的集群 2.免密:node01,node02 node02: cd ~/.ssh ssh-keygen -t dsa -P ...

  9. python_实现选课系统

    校园管理系统 角色: 学校.学员.课程.讲师 要求: 1. 创建北京.上海 2 所学校 2. 创建linux , python , go 3个课程 , linux\py 在北京开, go 在上海开 3 ...

  10. 被弃用的php函数以及用来替代的函数

    下面列举了部分被弃用的函数: call_user_method()(使用 call_user_func() 替代) call_user_method_array() (使用 call_user_fun ...