Skip to content
This repository was archived by the owner on Sep 4, 2025. It is now read-only.

Commit 1847e3c

Browse files
authored
Merge pull request #3168 from alibaba/bugfix
Bugfix
2 parents f8eb672 + 0716764 commit 1847e3c

File tree

157 files changed

+2771
-1645
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

157 files changed

+2771
-1645
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ easyexcel重写了poi对07版Excel的解析,一个3M的excel用POI sax解析
3131
<dependency>
3232
<groupId>com.alibaba</groupId>
3333
<artifactId>easyexcel</artifactId>
34-
<version>3.2.1</version>
34+
<version>3.3.0</version>
3535
</dependency>
3636
```
3737

README_EN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ DEMO:[https://github.com/alibaba/easyexcel/blob/master/src/test/java/com/aliba
122122
* 1. Create an entity object, refer to{@link DownloadData}.
123123
* Each property of the entity object corresponds to a specific field of Excel
124124
* 2. Specify the returned properties
125-
* 3. Invoke wirte function, then the OutputStream is automatically closed when it ends.
125+
* 3. Invoke write function, then the OutputStream is automatically closed when it ends.
126126
* </p>
127127
*/
128128
@GetMapping("download")

easyexcel-core/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,9 @@
4040
<groupId>org.ehcache</groupId>
4141
<artifactId>ehcache</artifactId>
4242
</dependency>
43+
<dependency>
44+
<groupId>commons-io</groupId>
45+
<artifactId>commons-io</artifactId>
46+
</dependency>
4347
</dependencies>
4448
</project>

easyexcel-core/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.alibaba.excel.read.metadata.holder.xls.XlsReadWorkbookHolder;
2020
import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadWorkbookHolder;
2121
import com.alibaba.excel.support.ExcelTypeEnum;
22+
import com.alibaba.excel.util.ClassUtils;
2223
import com.alibaba.excel.util.DateUtils;
2324
import com.alibaba.excel.util.FileUtils;
2425
import com.alibaba.excel.util.NumberDataFormatterUtils;
@@ -212,6 +213,7 @@ public void finish() {
212213
private void removeThreadLocalCache() {
213214
NumberDataFormatterUtils.removeThreadLocalCache();
214215
DateUtils.removeThreadLocalCache();
216+
ClassUtils.removeThreadLocalCache();
215217
}
216218

217219
private void clearEncrypt03() {

easyexcel-core/src/main/java/com/alibaba/excel/analysis/csv/CsvExcelReadExecutor.java

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.alibaba.excel.analysis.csv;
22

33
import java.io.IOException;
4+
import java.io.InputStream;
45
import java.io.InputStreamReader;
56
import java.nio.file.Files;
67
import java.util.ArrayList;
@@ -11,6 +12,7 @@
1112

1213
import com.alibaba.excel.analysis.ExcelReadExecutor;
1314
import com.alibaba.excel.context.csv.CsvReadContext;
15+
import com.alibaba.excel.enums.ByteOrderMarkEnum;
1416
import com.alibaba.excel.enums.CellDataTypeEnum;
1517
import com.alibaba.excel.enums.RowTypeEnum;
1618
import com.alibaba.excel.exception.ExcelAnalysisException;
@@ -27,6 +29,7 @@
2729
import org.apache.commons.csv.CSVFormat;
2830
import org.apache.commons.csv.CSVParser;
2931
import org.apache.commons.csv.CSVRecord;
32+
import org.apache.commons.io.input.BOMInputStream;
3033

3134
/**
3235
* read executor
@@ -82,17 +85,26 @@ public void execute() {
8285
private CSVParser csvParser() throws IOException {
8386
CsvReadWorkbookHolder csvReadWorkbookHolder = csvReadContext.csvReadWorkbookHolder();
8487
CSVFormat csvFormat = csvReadWorkbookHolder.getCsvFormat();
85-
88+
ByteOrderMarkEnum byteOrderMark = ByteOrderMarkEnum.valueOfByCharsetName(
89+
csvReadContext.csvReadWorkbookHolder().getCharset().name());
8690
if (csvReadWorkbookHolder.getMandatoryUseInputStream()) {
87-
return csvFormat.parse(
88-
new InputStreamReader(csvReadWorkbookHolder.getInputStream(), csvReadWorkbookHolder.getCharset()));
91+
return buildCsvParser(csvFormat, csvReadWorkbookHolder.getInputStream(), byteOrderMark);
8992
}
9093
if (csvReadWorkbookHolder.getFile() != null) {
91-
return csvFormat.parse(new InputStreamReader(Files.newInputStream(csvReadWorkbookHolder.getFile().toPath()),
92-
csvReadWorkbookHolder.getCharset()));
94+
return buildCsvParser(csvFormat, Files.newInputStream(csvReadWorkbookHolder.getFile().toPath()),
95+
byteOrderMark);
96+
}
97+
return buildCsvParser(csvFormat, csvReadWorkbookHolder.getInputStream(), byteOrderMark);
98+
}
99+
100+
private CSVParser buildCsvParser(CSVFormat csvFormat, InputStream inputStream, ByteOrderMarkEnum byteOrderMark)
101+
throws IOException {
102+
if (byteOrderMark == null) {
103+
return csvFormat.parse(
104+
new InputStreamReader(inputStream, csvReadContext.csvReadWorkbookHolder().getCharset()));
93105
}
94-
return csvFormat.parse(
95-
new InputStreamReader(csvReadWorkbookHolder.getInputStream(), csvReadWorkbookHolder.getCharset()));
106+
return csvFormat.parse(new InputStreamReader(new BOMInputStream(inputStream, byteOrderMark.getByteOrderMark()),
107+
csvReadContext.csvReadWorkbookHolder().getCharset()));
96108
}
97109

98110
private void dealRecord(CSVRecord record, int rowIndex) {

easyexcel-core/src/main/java/com/alibaba/excel/analysis/v07/handlers/sax/SharedStringsTableHandler.java

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,40 @@
1+
/* ====================================================================
2+
Licensed to the Apache Software Foundation (ASF) under one or more
3+
contributor license agreements. See the NOTICE file distributed with
4+
this work for additional information regarding copyright ownership.
5+
The ASF licenses this file to You under the Apache License, Version 2.0
6+
(the "License"); you may not use this file except in compliance with
7+
the License. You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
==================================================================== */
17+
118
package com.alibaba.excel.analysis.v07.handlers.sax;
219

3-
import org.xml.sax.Attributes;
4-
import org.xml.sax.helpers.DefaultHandler;
20+
import java.util.regex.Matcher;
21+
import java.util.regex.Pattern;
522

623
import com.alibaba.excel.cache.ReadCache;
724
import com.alibaba.excel.constant.ExcelXmlConstants;
825

26+
import org.xml.sax.Attributes;
27+
import org.xml.sax.helpers.DefaultHandler;
28+
929
/**
1030
* Sax read sharedStringsTable.xml
1131
*
1232
* @author Jiaju Zhuang
1333
*/
1434
public class SharedStringsTableHandler extends DefaultHandler {
1535

36+
private static final Pattern UTF_PATTTERN = Pattern.compile("_x([0-9A-Fa-f]{4})_");
37+
1638
/**
1739
* The final piece of data
1840
*/
@@ -86,7 +108,7 @@ public void endElement(String uri, String localName, String name) {
86108
if (currentData == null) {
87109
readCache.put(null);
88110
} else {
89-
readCache.put(currentData.toString());
111+
readCache.put(utfDecode(currentData.toString()));
90112
}
91113
break;
92114
case ExcelXmlConstants.SHAREDSTRINGS_RPH_TAG:
@@ -109,4 +131,51 @@ public void characters(char[] ch, int start, int length) {
109131
}
110132
currentElementData.append(ch, start, length);
111133
}
134+
135+
/**
136+
* from poi XSSFRichTextString
137+
*
138+
* @param value the string to decode
139+
* @return the decoded string or null if the input string is null
140+
* <p>
141+
* For all characters which cannot be represented in XML as defined by the XML 1.0 specification,
142+
* the characters are escaped using the Unicode numerical character representation escape character
143+
* format _xHHHH_, where H represents a hexadecimal character in the character's value.
144+
* <p>
145+
* Example: The Unicode character 0D is invalid in an XML 1.0 document,
146+
* so it shall be escaped as <code>_x000D_</code>.
147+
* </p>
148+
* See section 3.18.9 in the OOXML spec.
149+
* @see org.apache.poi.xssf.usermodel.XSSFRichTextString#utfDecode(String)
150+
*/
151+
static String utfDecode(String value) {
152+
if (value == null || !value.contains("_x")) {
153+
return value;
154+
}
155+
156+
StringBuilder buf = new StringBuilder();
157+
Matcher m = UTF_PATTTERN.matcher(value);
158+
int idx = 0;
159+
while (m.find()) {
160+
int pos = m.start();
161+
if (pos > idx) {
162+
buf.append(value, idx, pos);
163+
}
164+
165+
String code = m.group(1);
166+
int icode = Integer.decode("0x" + code);
167+
buf.append((char)icode);
168+
169+
idx = m.end();
170+
}
171+
172+
// small optimization: don't go via StringBuilder if not necessary,
173+
// the encodings are very rare, so we should almost always go via this shortcut.
174+
if (idx == 0) {
175+
return value;
176+
}
177+
178+
buf.append(value.substring(idx));
179+
return buf.toString();
180+
}
112181
}

easyexcel-core/src/main/java/com/alibaba/excel/context/WriteContextImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ private void addOneRowOfHeadDataToExcel(Row row, Integer rowIndex, Map<Integer,
265265
Head head = entry.getValue();
266266
int columnIndex = entry.getKey();
267267
ExcelContentProperty excelContentProperty = ClassUtils.declaredExcelContentProperty(null,
268-
currentWriteHolder.excelWriteHeadProperty().getHeadClazz(), head.getFieldName());
268+
currentWriteHolder.excelWriteHeadProperty().getHeadClazz(), head.getFieldName(), currentWriteHolder);
269269

270270
CellWriteHandlerContext cellWriteHandlerContext = WriteHandlerUtils.createCellWriteHandlerContext(this, row,
271271
rowIndex, head, columnIndex, relativeRowIndex, Boolean.TRUE, excelContentProperty);
@@ -427,6 +427,7 @@ public void finish(boolean onException) {
427427
private void removeThreadLocalCache() {
428428
NumberDataFormatterUtils.removeThreadLocalCache();
429429
DateUtils.removeThreadLocalCache();
430+
ClassUtils.removeThreadLocalCache();
430431
}
431432

432433
@Override

easyexcel-core/src/main/java/com/alibaba/excel/converters/DefaultConverterLoader.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,6 @@ private static void initAllConverter() {
115115
putAllConverter(new StringNumberConverter());
116116
putAllConverter(new StringStringConverter());
117117
putAllConverter(new StringErrorConverter());
118-
119-
putAllConverter(new BigIntegerStringConverter());
120118
}
121119

122120
private static void initDefaultWriteConverter() {
@@ -154,7 +152,6 @@ private static void initDefaultWriteConverter() {
154152
putWriteStringConverter(new LongStringConverter());
155153
putWriteStringConverter(new ShortStringConverter());
156154
putWriteStringConverter(new StringStringConverter());
157-
putWriteStringConverter(new BigIntegerStringConverter());
158155
}
159156

160157
/**
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package com.alibaba.excel.enums;
2+
3+
import java.nio.charset.Charset;
4+
import java.util.Map;
5+
6+
import com.alibaba.excel.util.MapUtils;
7+
8+
import lombok.Getter;
9+
import org.apache.commons.io.ByteOrderMark;
10+
11+
/**
12+
* byte order mark
13+
*
14+
* @author Jiaju Zhuang
15+
*/
16+
@Getter
17+
public enum ByteOrderMarkEnum {
18+
19+
/**
20+
* UTF_8
21+
*/
22+
UTF_8(ByteOrderMark.UTF_8),
23+
/**
24+
* UTF_16BE
25+
*/
26+
UTF_16BE(ByteOrderMark.UTF_16BE),
27+
/**
28+
* UTF_16LE
29+
*/
30+
UTF_16LE(ByteOrderMark.UTF_16LE),
31+
/**
32+
* UTF_32BE
33+
*/
34+
UTF_32BE(ByteOrderMark.UTF_32BE),
35+
/**
36+
* UTF_32LE
37+
*/
38+
UTF_32LE(ByteOrderMark.UTF_32LE),
39+
40+
;
41+
42+
final ByteOrderMark byteOrderMark;
43+
final String stringPrefix;
44+
45+
ByteOrderMarkEnum(ByteOrderMark byteOrderMark) {
46+
this.byteOrderMark = byteOrderMark;
47+
Charset charset = Charset.forName(byteOrderMark.getCharsetName());
48+
this.stringPrefix = new String(byteOrderMark.getBytes(), charset);
49+
}
50+
51+
/**
52+
* store character aliases corresponding to `ByteOrderMark` prefix
53+
*/
54+
private static final Map<String, ByteOrderMarkEnum> CHARSET_BYTE_ORDER_MARK_MAP = MapUtils.newHashMap();
55+
56+
static {
57+
for (ByteOrderMarkEnum value : ByteOrderMarkEnum.values()) {
58+
CHARSET_BYTE_ORDER_MARK_MAP.put(value.getByteOrderMark().getCharsetName(), value);
59+
}
60+
}
61+
62+
public static ByteOrderMarkEnum valueOfByCharsetName(String charsetName) {
63+
return CHARSET_BYTE_ORDER_MARK_MAP.get(charsetName);
64+
}
65+
66+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.alibaba.excel.enums;
2+
3+
/**
4+
* cache locaciton
5+
*
6+
* @author Jiaju Zhuang
7+
**/
8+
public enum CacheLocationEnum {
9+
/**
10+
* The cache will be stored in {@code ThreadLocal}, and will be cleared when the excel read and write is completed.
11+
*/
12+
THREAD_LOCAL,
13+
14+
/**
15+
* The cache will not be cleared unless the app is stopped.
16+
*/
17+
MEMORY,
18+
19+
/**
20+
* No caching.It may lose some of performance.
21+
*/
22+
NONE;
23+
}

0 commit comments

Comments
 (0)