zoukankan      html  css  js  c++  java
  • 解决CsvWriter:中文乱码、末尾行多一行空格(/r)、非第一列空字符串""显示null问题

     一:主要内容

    • 解决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类的基础上做了一些修改

      1 /**
      2  * Copyright (C), 2015-2019, XXX有限公司
      3  * FileName: CsvWriterExtend
      4  * Author:   yml
      5  * Date:     2019/5/17 15:42
      6  * Description:
      7  * History:
      8  * <author>          <time>          <version>          <desc>
      9  * tester           2019.5.17           1.0.0              优化CsvWriter工具
     10  */
     11 package com.test.csv.tool;
     12 
     13 import com.csvreader.CsvWriter;
     14 
     15 import java.io.*;
     16 import java.nio.charset.Charset;
     17 
     18 /**
     19  * @创建人 tester
     20  * @创建时间 2019/5/17
     21  * @描述 优化CsvWriter工具,解决了写入csv打开后中文乱码问题,解决了写入csv最后一行有/r换行的问题
     22  *
     23  */
     24 public class CsvWriterExtend extends CsvWriter {
     25     private PrintWriter outputStream;
     26     private String fileName;
     27     private boolean firstColumn;
     28     private boolean useCustomRecordDelimiter;
     29     private Charset charset;
     30     private CsvWriterExtend.UserSettings userSettings;
     31     private boolean initialized;
     32     private boolean closed;
     33     public static final int ESCAPE_MODE_DOUBLED = 1;
     34     public static final int ESCAPE_MODE_BACKSLASH = 2;
     35     private String sheetFirstName;
     36 
     37     public CsvWriterExtend(String var1, char var2, Charset var3,String sheetFirstName) {
     38         super(var1,var2,var3);
     39         this.outputStream = null;
     40         this.fileName = null;
     41         this.firstColumn = true;
     42         this.useCustomRecordDelimiter = false;
     43         this.charset = null;
     44         this.userSettings = new CsvWriterExtend.UserSettings();
     45         this.initialized = false;
     46         this.closed = false;
     47         //1:这里加了一个csv表头的第一个名字字段,用来解决第一个问题:中文乱码问题
     48         this.sheetFirstName = sheetFirstName;
     49         if (var1 == null) {
     50             throw new IllegalArgumentException("Parameter fileName can not be null.");
     51         } else if (var3 == null) {
     52             throw new IllegalArgumentException("Parameter charset can not be null.");
     53         } else {
     54             this.fileName = var1;
     55             this.userSettings.Delimiter = var2;
     56             this.charset = var3;
     57         }
     58     }
     59 
     60     public CsvWriterExtend(Writer var1, char var2) {
     61         super(var1,var2);
     62         this.outputStream = null;
     63         this.fileName = null;
     64         this.firstColumn = true;
     65         this.useCustomRecordDelimiter = false;
     66         this.charset = null;
     67         this.userSettings = new CsvWriterExtend.UserSettings();
     68         this.initialized = false;
     69         this.closed = false;
     70         if (var1 == null) {
     71             throw new IllegalArgumentException("Parameter outputStream can not be null.");
     72         } else {
     73             this.outputStream = new PrintWriter(var1);
     74             this.userSettings.Delimiter = var2;
     75             this.initialized = true;
     76         }
     77     }
     78 
     79     public CsvWriterExtend(OutputStream var1, char var2, Charset var3) {
     80         this(new OutputStreamWriter(var1, var3), var2);
     81     }
     82 
     83     public char getDelimiter() {
     84         return this.userSettings.Delimiter;
     85     }
     86 
     87     public void setDelimiter(char var1) {
     88         this.userSettings.Delimiter = var1;
     89     }
     90 
     91     public char getRecordDelimiter() {
     92         return this.userSettings.RecordDelimiter;
     93     }
     94 
     95     public void setRecordDelimiter(char var1) {
     96         this.useCustomRecordDelimiter = true;
     97         this.userSettings.RecordDelimiter = var1;
     98     }
     99 
    100     public char getTextQualifier() {
    101         return this.userSettings.TextQualifier;
    102     }
    103 
    104     public void setTextQualifier(char var1) {
    105         this.userSettings.TextQualifier = var1;
    106     }
    107 
    108     public boolean getUseTextQualifier() {
    109         return this.userSettings.UseTextQualifier;
    110     }
    111 
    112     public void setUseTextQualifier(boolean var1) {
    113         this.userSettings.UseTextQualifier = var1;
    114     }
    115 
    116     public int getEscapeMode() {
    117         return this.userSettings.EscapeMode;
    118     }
    119 
    120     public void setEscapeMode(int var1) {
    121         this.userSettings.EscapeMode = var1;
    122     }
    123 
    124     public void setComment(char var1) {
    125         this.userSettings.Comment = var1;
    126     }
    127 
    128     public char getComment() {
    129         return this.userSettings.Comment;
    130     }
    131 
    132     public boolean getForceQualifier() {
    133         return this.userSettings.ForceQualifier;
    134     }
    135 
    136     public void setForceQualifier(boolean var1) {
    137         this.userSettings.ForceQualifier = var1;
    138     }
    139 
    140     public void write(String var1, boolean var2) throws IOException {
    141         this.checkClosed();
    142         this.checkInit();
    143         if (var1 == null) {
    144             var1 = "";
    145         }
    146         //2:这里加了一个判断条件,用来解决第一个问题:中文乱码问题
    147         //加的目的是:如果是写入bom则bom后面不追加逗号,即在bom后面和第一个表头前面,即两者之间不追加逗号,sheetFirstName为第一个表头的名字根据实际传入
    148         if (!this.firstColumn && !var1.contentEquals(sheetFirstName) ){
    149             this.outputStream.write(this.userSettings.Delimiter);
    150         }
    151 
    152         boolean var3 = this.userSettings.ForceQualifier;
    153         if (!var2 && var1.length() > 0) {
    154             var1 = var1.trim();
    155         }
    156 
    157         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)) {
    158             var3 = true;
    159         }
    160 
    161         if (this.userSettings.UseTextQualifier && !var3 && var1.length() > 0 && var2) {
    162             char var4 = var1.charAt(0);
    163             if (var4 == ' ' || var4 == '	') {
    164                 var3 = true;
    165             }
    166 
    167             if (!var3 && var1.length() > 1) {
    168                 char var5 = var1.charAt(var1.length() - 1);
    169                 if (var5 == ' ' || var5 == '	') {
    170                     var3 = true;
    171                 }
    172             }
    173         }
    174         //3:这里加了一个if语句,是为了解决第三个问题:csv""显示null的问题
    175         if(!this.firstColumn && var1.length()==0){
    176             var3=true;
    177         }
    178         if (var3) {
    179             this.outputStream.write(this.userSettings.TextQualifier);
    180             if (this.userSettings.EscapeMode == 2) {
    181                 var1 = replace(var1, "\", "\\");
    182                 var1 = replace(var1, "" + this.userSettings.TextQualifier, "\" + this.userSettings.TextQualifier);
    183             } else {
    184                 var1 = replace(var1, "" + this.userSettings.TextQualifier, "" + this.userSettings.TextQualifier + this.userSettings.TextQualifier);
    185             }
    186         } else if (this.userSettings.EscapeMode == 2) {
    187             var1 = replace(var1, "\", "\\");
    188             var1 = replace(var1, "" + this.userSettings.Delimiter, "\" + this.userSettings.Delimiter);
    189             if (this.useCustomRecordDelimiter) {
    190                 var1 = replace(var1, "" + this.userSettings.RecordDelimiter, "\" + this.userSettings.RecordDelimiter);
    191             } else {
    192                 var1 = replace(var1, "
    ", "\
    ");
    193                 var1 = replace(var1, "
    ", "\
    ");
    194             }
    195 
    196             if (this.firstColumn && var1.length() > 0 && var1.charAt(0) == this.userSettings.Comment) {
    197                 if (var1.length() > 1) {
    198                     var1 = "\" + this.userSettings.Comment + var1.substring(1);
    199                 } else {
    200                     var1 = "\" + this.userSettings.Comment;
    201                 }
    202             }
    203         }
    204 
    205 
    206         this.outputStream.write(var1);
    207 
    208         if (var3) {
    209             this.outputStream.write(this.userSettings.TextQualifier);
    210         }
    211 
    212         this.firstColumn = false;
    213     }
    214 
    215     public void write(String var1) throws IOException {
    216         this.write(var1, false);
    217     }
    218 
    219     public void writeComment(String var1) throws IOException {
    220         this.checkClosed();
    221         this.checkInit();
    222         this.outputStream.write(this.userSettings.Comment);
    223         this.outputStream.write(var1);
    224         if (this.useCustomRecordDelimiter) {
    225             this.outputStream.write(this.userSettings.RecordDelimiter);
    226         } else {
    227             this.outputStream.println();
    228         }
    229 
    230         this.firstColumn = true;
    231     }
    232 
    233     public void writeRecord(String[] var1, boolean var2) throws IOException {
    234         if (var1 != null && var1.length > 0) {
    235             for(int var3 = 0; var3 < var1.length; ++var3) {
    236                 this.write(var1[var3], var2);
    237             }
    238 
    239             this.endRecord();
    240         }
    241 
    242     }
    243 
    244     public void writeRecord(String[] var1) throws IOException {
    245         this.writeRecord(var1, false);
    246     }
    247     
    248     public void writeLastRecord(String[] var1) throws IOException {
    249         this.writeLastRecord(var1, false);
    250     }
    251     
    252     //4:这里加了两个方法writeLastRecord和endLastRecord,用来解决第二个问题:某尾总是多一行空行的问题
    253     public void writeLastRecord(String[] var1, boolean var2) throws IOException {
    254         if (var1 != null && var1.length > 0) {
    255             for(int var3 = 0; var3 < var1.length; ++var3) {
    256                 this.write(var1[var3], var2);
    257             }
    258 
    259             this.endLastRecord();
    260         }
    261 
    262     }
    263     public void endLastRecord() throws IOException {
    264         this.checkClosed();
    265         this.checkInit();
    266         if (this.useCustomRecordDelimiter) {
    267             this.outputStream.write(this.userSettings.RecordDelimiter);
    268         } else {//主要在下面这一行,当执行这个方法来结尾的时候是不追加换行符的
    269             this.outputStream.print("");
    270         }
    271 
    272         this.firstColumn = true;
    273     }
    274 
    275     public void endRecord() throws IOException {
    276         this.checkClosed();
    277         this.checkInit();
    278         if (this.useCustomRecordDelimiter) {
    279             this.outputStream.write(this.userSettings.RecordDelimiter);
    280         } else {
    281             this.outputStream.println();
    282         }
    283 
    284         this.firstColumn = true;
    285     }
    286 
    287     private void checkInit() throws IOException {
    288         if (!this.initialized) {
    289             if (this.fileName != null) {
    290                 this.outputStream = new PrintWriter(new OutputStreamWriter(new FileOutputStream(this.fileName), this.charset));
    291             }
    292 
    293             this.initialized = true;
    294         }
    295 
    296     }
    297 
    298     public void flush() {
    299         this.outputStream.flush();
    300     }
    301 
    302     public void close() {
    303         if (!this.closed) {
    304             this.close(true);
    305             this.closed = true;
    306         }
    307 
    308     }
    309 
    310     private void close(boolean var1) {
    311         if (!this.closed) {
    312             if (var1) {
    313                 this.charset = null;
    314             }
    315 
    316             try {
    317                 if (this.initialized) {
    318                     this.outputStream.close();
    319                 }
    320             } catch (Exception var3) {
    321                 ;
    322             }
    323 
    324             this.outputStream = null;
    325             this.closed = true;
    326         }
    327 
    328     }
    329 
    330     private void checkClosed() throws IOException {
    331         if (this.closed) {
    332             throw new IOException("This instance of the CsvWriter class has already been closed.");
    333         }
    334     }
    335 
    336     protected void finalize() {
    337         this.close(false);
    338     }
    339 
    340     public static String replace(String var0, String var1, String var2) {
    341         int var3 = var1.length();
    342         int var4 = var0.indexOf(var1);
    343         if (var4 <= -1) {
    344             return var0;
    345         } else {
    346             StringBuffer var5 = new StringBuffer();
    347 
    348             int var6;
    349             for(var6 = 0; var4 != -1; var4 = var0.indexOf(var1, var6)) {
    350                 var5.append(var0.substring(var6, var4));
    351                 var5.append(var2);
    352                 var6 = var4 + var3;
    353             }
    354 
    355             var5.append(var0.substring(var6));
    356             return var5.toString();
    357         }
    358     }
    359 
    360     private class UserSettings {
    361         public char TextQualifier = '"';
    362         public boolean UseTextQualifier = true;
    363         public char Delimiter = ',';
    364         public char RecordDelimiter = 0;
    365         public char Comment = '#';
    366         public int EscapeMode = 1;
    367         public boolean ForceQualifier = false;
    368 
    369         public UserSettings() {
    370         }
    371     }
    372 
    373     private class Letters {
    374         public static final char LF = '
    ';
    375         public static final char CR = '
    ';
    376         public static final char QUOTE = '"';
    377         public static final char COMMA = ',';
    378         public static final char SPACE = ' ';
    379         public static final char TAB = '	';
    380         public static final char POUND = '#';
    381         public static final char BACKSLASH = '\';
    382         public static final char NULL = 'u0000';
    383 
    384         private Letters() {
    385         }
    386     }
    387 }            

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

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

     1  /**
     2      * 写csv方法
     3      */
     4     public static <T> void writeCSV(Collection<T> dataset, String csvFilePath, String[] csvHeaders) {
     5 
     6         try {
     7             //集合长度,和循环次数,当循环到最后一条记录时不在末尾插入换行符
     8             int datasetLength = dataset.size();
     9             int loop=1;
    10             // 定义路径,分隔符,编码d,第一个表头名称
    11             //如果是写入bom则bom后面不追加逗号,即在bom后面和第一个表头前面,即两者之间不追加逗号,sheetFirstName为第一个表头的名字根据实际传入
    12             CsvWriterExtend csvWriter = new CsvWriterExtend(csvFilePath, ',', Charset.forName("UTF-8"),"username"); // 写表头
    13             //如果是写入bom解决文件乱码,则不在bom后面追加,号分隔符
    14             csvWriter.write("ufeff");
    15             csvWriter.writeRecord(csvHeaders); // 写内容
    16             // 遍历集合
    17             Iterator<T> it = dataset.iterator();
    18             while (it.hasNext()) {
    19                 T t = (T) it.next();
    20                 //获取类属性
    21                 Field[] fields = t.getClass().getDeclaredFields();
    22                 String[] csvContent=new String[fields.length];
    23                 for (short i = 0; i < fields.length; i++) {
    24                     Field field = fields[i];
    25                     String fieldName = field.getName();
    26                     String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
    27                     try {
    28                         Class tCls = t.getClass();
    29                         Method getMethod = tCls.getMethod(getMethodName,new Class[] {});
    30                         Object value = getMethod.invoke(t, new Object[] {});
    31                         if (value == null) {
    32                             continue;
    33                         }
    34                         //取值并赋给数组
    35                         String textvalue=value.toString();
    36                         csvContent[i]=textvalue;
    37                     }catch (Exception e) {
    38                         e.getStackTrace();
    39                     }
    40                 }
    41                 if(loop!=datasetLength){
    42                     //迭代插入记录
    43                     csvWriter.writeRecord(csvContent);
    44                 }else{
    45                     //插入最后一条记录
    46                     csvWriter.writeLastRecord(csvContent);
    47                 }
    48 
    49                 loop=loop+1;
    50                 for(String csvs:csvContent) {
    51                     System.out.println("记录数据:" + csvs);
    52                 }
    53             } csvWriter.close();
    54             System.out.println("<--------CSV文件写入成功-------->");
    55         } catch (IOException e) {
    56             e.printStackTrace();
    57         }
    58     }

    调用csv方法即执行类

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

    生成csv的效果如图:

    四:备注

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

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

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

  • 相关阅读:
    HTML5标签
    CTF web之旅 45
    CTF web之旅44
    CTF web之旅 43
    CTF web之旅 42
    CTF web之旅41
    CTF web之旅40
    CTF web之旅 39
    CTF web之旅 38
    CTF web之旅 37
  • 原文地址:https://www.cnblogs.com/miaomiaokaixin/p/10885302.html
Copyright © 2011-2022 走看看