1 packagetest;2
3 importlombok.extern.slf4j.Slf4j;4
5 importjava.io.BufferedReader;6 importjava.io.FileInputStream;7 importjava.io.IOException;8 importjava.io.InputStreamReader;9 importjava.util.ArrayList;10 importjava.util.HashMap;11 importjava.util.List;12 importjava.util.Map;13
14 @Slf4j15 public classCSVFileUtil {16 /**
17 * CSV文件编码18 */
19 private static final String ENCODE = "UTF-8";20
21 /**
22 * 读取CSV文件得到List,默认使用UTF-8编码23 *@paramfileName 文件路径24 *@return
25 */
26 public static ListgetLines(String fileName) {27 returngetLines(fileName, ENCODE);28 }29
30 /**
31 * 读取CSV文件得到List32 *@paramfileName 文件路径33 *@paramencode 编码34 *@return
35 */
36 public static ListgetLines(String fileName, String encode) {37 List lines = new ArrayList();38 BufferedReader br = null;39 InputStreamReader isr = null;40 FileInputStream fis = null;41 try{42 fis = newFileInputStream(fileName);43 isr = newInputStreamReader(fis, encode);44 br = newBufferedReader(isr);45 String line;46 while ((line = br.readLine()) != null) {47 StringBuilder sb = newStringBuilder();48 sb.append(line);49 boolean readNext = countChar(sb.toString(), '"', 0) % 2 == 1;50 //如果双引号是奇数的时候继续读取。考虑有换行的是情况
51 while(readNext) {52 line =br.readLine();53 if (line == null) {54 return null;55 }56 sb.append(line);57 readNext = countChar(sb.toString(), '"', 0) % 2 == 1;58 }59 lines.add(sb.toString());60 }61 } catch(Exception e) {62 log.error("Read CSV file failure :{}", e);63 } finally{64 try{65 if (br != null) {66 br.close();67 }68 if (isr != null) {69 isr.close();70 }71 if (fis != null) {72 fis.close();73 }74 } catch(IOException e) {75 log.error("Close stream failure :{}", e);76 }77 }78 returnlines;79 }80
81 public staticString[] fromCSVLine(String source) {82 return fromCSVLine(source, 0);83 }84
85 /**
86 * 把CSV文件的一行转换成字符串数组。指定数组长度,不够长度的部分设置为null87 *@paramsource88 *@paramsize89 *@return
90 */
91 public static String[] fromCSVLine(String source, intsize) {92 List list =fromCSVLineToArray(source);93 if (size
101 public staticList fromCSVLineToArray(String source) {102 if (source == null || source.length() == 0) {103 return newArrayList();104 }105 int currentPosition = 0;106 int maxPosition =source.length();107 int nextComa = 0;108 List list = newArrayList();109 while (currentPosition
120 /**
121 * 把字符串类型的数组转换成一个CSV行。(输出CSV文件的时候用)122 *123 *@paramarr124 *@return
125 */
126 public staticString toCSVLine(String[] arr) {127 if (arr == null) {128 return "";129 }130 StringBuilder sb = newStringBuilder();131 for (int i = 0; i < arr.length; i++) {132 String item =addQuote(arr[i]);133 sb.append(item);134 if (arr.length - 1 !=i) {135 sb.append(",");136 }137 }138 returnsb.toString();139 }140
141 /**
142 * 将list的第一行作为Map的key,下面的列作为Map的value143 *@paramlist144 *@return
145 */
146 public static List> parseList(Listlist) {147 List> resultList = new ArrayList>();148 String firstLine = list.get(0);149 String[] fields = firstLine.split(",");150 for (int i = 1; i < list.size(); i++) {151 String valueLine =list.get(i);152 String[] valueItems =CSVFileUtil.fromCSVLine(valueLine);153 Map map = new HashMap();154 for (int j = 0; j < fields.length; j++) {155 map.put(fields[j], valueItems[j]);156 }157 resultList.add(map);158 }159 returnresultList;160 }161
162 /**
163 * 字符串类型的List转换成一个CSV行。(输出CSV文件的时候用)164 *165 *@paramstrArrList166 *@return
167 */
168 public staticString toCSVLine(ArrayList strArrList) {169 if (strArrList == null) {170 return "";171 }172 String[] strArray = newString[strArrList.size()];173 for (int idx = 0; idx < strArrList.size(); idx++) {174 strArray[idx] =(String) strArrList.get(idx);175 }176 returntoCSVLine(strArray);177 }178
179 /**
180 * 计算指定字符的个数181 *182 *@paramstr 文字列183 *@paramc 字符184 *@paramstart 开始位置185 *@return个数186 */
187 private static int countChar(String str, char c, intstart) {188 int index =str.indexOf(c, start);189 return index == -1 ? 0 : countChar(str, c, index + 1) + 1;190 }191
192 /**
193 * 查询下一个逗号的位置。194 *195 *@paramsource 文字列196 *@paramst 检索开始位置197 *@return下一个逗号的位置。198 */
199 private static int nextComma(String source, intst) {200 int maxPosition =source.length();201 boolean inquote = false;202 while (st
214 /**
215 * 取得下一个字符串216 *217 *@paramsource218 *@paramst219 *@paramnextComma220 *@return
221 */
222 private static String nextToken(String source, int st, intnextComma) {223 StringBuilder strb = newStringBuilder();224 int next =st;225 while (next
239 /**
240 * 在字符串的外侧加双引号。如果该字符串的内部有双引号的话,把"转换成""。241 *242 *@paramitem 字符串243 *@return处理过的字符串244 */
245 private staticString addQuote(String item) {246 if (item == null || item.length() == 0) {247 return "\"\"";248 }249 StringBuilder sb = newStringBuilder();250 sb.append('"');251 for (int idx = 0; idx < item.length(); idx++) {252 char ch =item.charAt(idx);253 if ('"' ==ch) {254 sb.append("\"\"");255 } else{256 sb.append(ch);257 }258 }259 sb.append('"');260 returnsb.toString();261 }262 }