diff --git a/easypoi-base/src/main/java/cn/afterturn/easypoi/csv/imports/CsvImportService.java b/easypoi-base/src/main/java/cn/afterturn/easypoi/csv/imports/CsvImportService.java index 73e5c1f..35300c9 100644 --- a/easypoi-base/src/main/java/cn/afterturn/easypoi/csv/imports/CsvImportService.java +++ b/easypoi-base/src/main/java/cn/afterturn/easypoi/csv/imports/CsvImportService.java @@ -14,6 +14,7 @@ import cn.afterturn.easypoi.handler.inter.IExcelModel; import cn.afterturn.easypoi.util.PoiPublicUtil; import cn.afterturn.easypoi.util.PoiReflectorUtil; import cn.afterturn.easypoi.util.PoiValidationUtil; +import cn.afterturn.easypoi.util.UnicodeInputStream; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.ReflectionToStringBuilder; import org.apache.poi.ss.usermodel.Cell; @@ -57,6 +58,9 @@ public class CsvImportService extends ImportBaseService { } getAllExcelField(targetId, fileds, excelParams, excelCollection, pojoClass, null, null); } + if(PoiPublicUtil.hasBom(inputstream)){ + inputstream = new UnicodeInputStream(inputstream); + } BufferedReader rows = new BufferedReader(new InputStreamReader(inputstream, params.getEncoding())); for (int j = 0; j < params.getTitleRows(); j++) { rows.readLine(); @@ -76,8 +80,11 @@ public class CsvImportService extends ImportBaseService { Object object = null; String[] cells; while ((row = rows.readLine()) != null) { + if(StringUtils.isEmpty(row)){ + continue; + } errorMsg = new StringBuilder(); - cells = row.split(params.getSpiltMark()); + cells = row.split(params.getSpiltMark(),-1); // 判断是集合元素还是不是集合元素,如果是就继续加入这个集合,不是就创建新的对象 // keyIndex 如果为空就不处理,仍然处理这一行 if (params.getKeyIndex() != null && (cells[params.getKeyIndex()] == null diff --git a/easypoi-base/src/main/java/cn/afterturn/easypoi/util/PoiPublicUtil.java b/easypoi-base/src/main/java/cn/afterturn/easypoi/util/PoiPublicUtil.java index b64f270..271be9e 100644 --- a/easypoi-base/src/main/java/cn/afterturn/easypoi/util/PoiPublicUtil.java +++ b/easypoi-base/src/main/java/cn/afterturn/easypoi/util/PoiPublicUtil.java @@ -1,6 +1,6 @@ /** * Copyright 2013-2015 JueYue (qrb.jueyue@gmail.com) - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -18,8 +18,7 @@ package cn.afterturn.easypoi.util; import static cn.afterturn.easypoi.util.PoiElUtil.*; import java.awt.image.BufferedImage; -import java.io.ByteArrayOutputStream; -import java.io.File; +import java.io.*; import java.lang.reflect.Field; import java.math.BigDecimal; import java.net.URISyntaxException; @@ -85,7 +84,7 @@ public final class PoiPublicUtil { /** * 彻底创建一个对象 - * + * * @param clazz * @return */ @@ -121,7 +120,7 @@ public final class PoiPublicUtil { /** * 获取class的 包括父类的 - * + * * @param clazz * @return */ @@ -159,9 +158,24 @@ public final class PoiPublicUtil { return strFileExtendName; } + + /** + * 判断流是否含有BOM + * @param in + * @return + * @throws IOException + */ + public static boolean hasBom(InputStream in) throws IOException { + byte[] head = new byte[3]; + in.read(head); + if(head[0]==-17 && head[1]==-69 && head[2] ==-65) { + return true; + } + return false; + } /** * 获取Excel2003图片 - * + * * @param sheet * 当前sheet对象 * @param workbook @@ -192,7 +206,7 @@ public final class PoiPublicUtil { /** * 获取Excel2007图片 - * + * * @param sheet * 当前sheet对象 * @param workbook @@ -222,7 +236,7 @@ public final class PoiPublicUtil { /** * 判断是不是集合的实现类 - * + * * @param clazz * @return */ @@ -232,7 +246,7 @@ public final class PoiPublicUtil { /** * 是不是java基础类 - * + * * @param field * @return */ @@ -253,7 +267,7 @@ public final class PoiPublicUtil { /** * 判断是否不要在这个excel操作中 - * + * * @param exclusionsList * @param field * @param targetId @@ -285,7 +299,7 @@ public final class PoiPublicUtil { /** * 判断是不是使用 - * + * * @param exportName * @param targetId * @return @@ -317,7 +331,7 @@ public final class PoiPublicUtil { * 2013-11-20 *@param entity *@return (byte[]) isAndType[0],(Integer)isAndType[1] - * @throws Exception + * @throws Exception */ public static Object[] getIsAndType(ImageEntity entity) throws Exception { Object[] result = new Object[2]; @@ -335,7 +349,7 @@ public final class PoiPublicUtil { /** * 获取参数值 - * + * * @param params * @param object * @return @@ -354,7 +368,7 @@ public final class PoiPublicUtil { /** * 解析数据 - * + * * @author JueYue * 2013-11-16 * @return @@ -379,7 +393,7 @@ public final class PoiPublicUtil { /** * 通过遍历过去对象值 - * + * * @param object * @param paramsArr * @param index diff --git a/easypoi-base/src/main/java/cn/afterturn/easypoi/util/UnicodeInputStream.java b/easypoi-base/src/main/java/cn/afterturn/easypoi/util/UnicodeInputStream.java new file mode 100644 index 0000000..a4b31fe --- /dev/null +++ b/easypoi-base/src/main/java/cn/afterturn/easypoi/util/UnicodeInputStream.java @@ -0,0 +1,183 @@ +package cn.afterturn.easypoi.util; + +/** + * @author by jueyue on 18-11-7. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.PushbackInputStream; + +public class UnicodeInputStream extends InputStream { + public static final UnicodeInputStream.UnicodeBOM UTF8_BOM = new UnicodeInputStream.UnicodeBOM("UTF-8", new byte[]{-17, -69, -65}); + public static final UnicodeInputStream.UnicodeBOM UTF16LE_BOM = new UnicodeInputStream.UnicodeBOM("UTF-16LE", new byte[]{-1, -2}); + public static final UnicodeInputStream.UnicodeBOM UTF16BE_BOM = new UnicodeInputStream.UnicodeBOM("UTF-16BE", new byte[]{-2, -1}); + public static final UnicodeInputStream.UnicodeBOM UTF32LE_BOM = new UnicodeInputStream.UnicodeBOM("UTF-32LE", new byte[]{-1, -2, 0, 0}); + public static final UnicodeInputStream.UnicodeBOM UTF32BE_BOM = new UnicodeInputStream.UnicodeBOM("UTF-32BE", new byte[]{0, 0, -2, -1}); + private static final int MAX_BOM_SIZE = 4; + private byte[] buf; + private int pos; + private final String encoding; + private final boolean skipBOM; + private final PushbackInputStream inputStream; + + public UnicodeInputStream(InputStream inputStream) throws IllegalStateException, IOException { + this(inputStream, true); + } + + public UnicodeInputStream(InputStream inputStream, boolean skipBOM) throws IllegalStateException, IOException { + this.buf = new byte[MAX_BOM_SIZE]; + this.pos = 0; + this.skipBOM = skipBOM; + this.inputStream = new PushbackInputStream(inputStream, MAX_BOM_SIZE); + + try { + this.encoding = this.readEncoding(); + } catch (IOException var5) { + IllegalStateException ex = new IllegalStateException("Could not read BOM from Stream"); + throw ex; + } + } + + public boolean isSkipBOM() { + return this.skipBOM; + } + + public String getEncodingFromStream() { + return this.encoding; + } + + protected String readEncoding() throws IOException { + this.pos = 0; + UnicodeInputStream.UnicodeBOM encoding = null; + if (this.readByte()) { + switch(this.buf[0]) { + case -17: + encoding = this.match(UTF8_BOM, (UnicodeInputStream.UnicodeBOM)null); + break; + case -2: + encoding = this.match(UTF16BE_BOM, (UnicodeInputStream.UnicodeBOM)null); + break; + case -1: + encoding = this.match(UTF16LE_BOM, (UnicodeInputStream.UnicodeBOM)null); + if (encoding != null) { + encoding = this.match(UTF32LE_BOM, encoding); + } + break; + case 0: + encoding = this.match(UTF32BE_BOM, (UnicodeInputStream.UnicodeBOM)null); + break; + default: + encoding = null; + } + } + + this.pushback(encoding); + return encoding != null ? encoding.getEncoding() : null; + } + + private final UnicodeInputStream.UnicodeBOM match(UnicodeInputStream.UnicodeBOM matchEncoding, UnicodeInputStream.UnicodeBOM noMatchEncoding) throws IOException { + byte[] bom = matchEncoding.getBytes(); + + for(int i = 0; i < bom.length; ++i) { + if (this.pos <= i && !this.readByte()) { + return noMatchEncoding; + } + + if (bom[i] != this.buf[i]) { + return noMatchEncoding; + } + } + + return matchEncoding; + } + + private final boolean readByte() throws IOException { + int res = this.inputStream.read(); + if (res == -1) { + return false; + } else if (this.pos >= this.buf.length) { + throw new IOException("BOM read error"); + } else { + this.buf[this.pos++] = (byte)res; + return true; + } + } + + private final void pushback(UnicodeInputStream.UnicodeBOM matchBOM) throws IOException { + int count = this.pos; + int start = 0; + if (matchBOM != null && this.skipBOM) { + start = matchBOM.getBytes().length; + count = this.pos - start; + if (count < 0) { + throw new IllegalStateException("Match has more bytes than available!"); + } + } + + this.inputStream.unread(this.buf, start, count); + } + + @Override + public void close() throws IOException { + this.inputStream.close(); + } + + @Override + public int available() throws IOException { + return this.inputStream.available(); + } + + @Override + public void mark(int readlimit) { + this.inputStream.mark(readlimit); + } + + @Override + public boolean markSupported() { + return this.inputStream.markSupported(); + } + + @Override + public int read() throws IOException { + return this.inputStream.read(); + } + + @Override + public int read(byte[] b) throws IOException { + return this.inputStream.read(b); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + return this.inputStream.read(b, off, len); + } + + @Override + public void reset() throws IOException { + this.inputStream.reset(); + } + + @Override + public long skip(long n) throws IOException { + return this.inputStream.skip(n); + } + + static final class UnicodeBOM { + private final String encoding; + private final byte[] bytes; + + private UnicodeBOM(String encoding, byte[] bytes) { + this.encoding = encoding; + this.bytes = bytes; + } + + String getEncoding() { + return this.encoding; + } + + byte[] getBytes() { + return this.bytes; + } + } +} \ No newline at end of file