diff --git a/CHANGELOG.md b/CHANGELOG.md index e1d284c2c..f83ef1638 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,12 +11,14 @@ * 【core】 修正DateUtil.thisWeekOfMonth注释错误(issue#614@Github) * 【core】 DateUtil增加toLocalDate等方法,DateTime更好的支持时区 * 【core】 BeanUtil.getProperty返回泛型对象(issue#I14PIW@Gitee) +* 【core】 FileTypeUtil使用扩展名辅助判断类型(issue#I14JBH@Gitee) ### Bug修复 * 【db】 修复MetaUtil.getTableMeta()方法未释放ResultSet的bug(issue#I148GH@Gitee) * 【core】 修复DateUtil.age闰年导致的问题(issue#I14BVN@Gitee) * 【extra】 修复ServletUtil.getCookie大小写问题(pr#79@Gitee) * 【core】 修复IdcardUtil.isValidCard18报错问题(issue#I14LTJ@Gitee) +* 【poi】 修复double值可能存在的精度问题(issue#I14FG1@Gitee) ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileTypeUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/FileTypeUtil.java index 172e5b6bc..f070c174e 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/FileTypeUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/FileTypeUtil.java @@ -11,13 +11,12 @@ import cn.hutool.core.util.StrUtil; /** * 文件类型判断工具类 - * - *
此工具根据文件的前几位bytes猜测文件类型,对于文本、zip判断不准确,对于视频、图片类型判断准确
- * - *需要注意的是,xlsx、docx等Office2007格式,全部识别为zip,因为新版采用了OpenXML格式,这些格式本质上是XML文件打包为zip
- * - * @author Looly * + *此工具根据文件的前几位bytes猜测文件类型,对于文本、zip判断不准确,对于视频、图片类型判断准确
+ * + *需要注意的是,xlsx、docx等Office2007格式,全部识别为zip,因为新版采用了OpenXML格式,这些格式本质上是XML文件打包为zip
+ * + * @author Looly */ public class FileTypeUtil { @@ -38,7 +37,6 @@ public class FileTypeUtil { fileTypeMap.put("7b5c727466315c616e73", "rtf"); // Rich Text Format (rtf) fileTypeMap.put("38425053000100000000", "psd"); // Photoshop (psd) fileTypeMap.put("46726f6d3a203d3f6762", "eml"); // Email [Outlook Express 6] (eml) - fileTypeMap.put("d0cf11e0a1b11ae10000", "doc"); // MS Excel 注意:word、msi 和 excel的文件头一样 fileTypeMap.put("5374616E64617264204A", "mdb"); // MS Access (mdb) fileTypeMap.put("252150532D41646F6265", "ps"); fileTypeMap.put("255044462d312e", "pdf"); // Adobe Acrobat (pdf) @@ -55,7 +53,8 @@ public class FileTypeUtil { fileTypeMap.put("235468697320636f6e66", "ini"); fileTypeMap.put("504B03040a0000000000", "jar"); fileTypeMap.put("504B0304140008000800", "jar"); - fileTypeMap.put("D0CF11E0A1B11AE10", "xls");// xls文件 + // MS Excel 注意:word、msi 和 excel的文件头一样 + fileTypeMap.put("d0cf11e0a1b11ae10", "xls"); fileTypeMap.put("504B0304", "zip"); fileTypeMap.put("4d5a9000030000000400", "exe");// 可执行文件 fileTypeMap.put("3c25402070616765206c", "jsp");// jsp文件 @@ -79,9 +78,9 @@ public class FileTypeUtil { /** * 增加文件类型映射null
*/
public static String getType(String fileStreamHexHead) {
for (Entrynull
* @throws IORuntimeException 读取流引起的异常
@@ -126,24 +125,59 @@ public class FileTypeUtil {
/**
* 根据文件流的头部信息获得文件类型
- *
+ *
+ * + * 1、无法识别类型默认按照扩展名识别 + * 2、xls、doc、msi头信息无法区分,按照扩展名区分 + * 3、zip可能为docx、xlsx、pptx、jar、war头信息无法区分,按照扩展名区分 + *+ * * @param file 文件 {@link File} * @return 类型,文件的扩展名,未找到为
null
* @throws IORuntimeException 读取文件引起的异常
*/
public static String getType(File file) throws IORuntimeException {
+ String typeName;
FileInputStream in = null;
try {
in = IoUtil.toStream(file);
- return getType(in);
+ typeName = getType(in);
} finally {
IoUtil.close(in);
}
+
+ if (null == typeName) {
+ // 未成功识别类型,扩展名辅助识别
+ typeName = FileUtil.extName(file);
+ } else if ("xls".equals(typeName)) {
+ // xls、doc、msi的头一样,使用扩展名辅助判断
+ final String extName = FileUtil.extName(file);
+ if ("doc".equalsIgnoreCase(extName)) {
+ typeName = "doc";
+ } else if ("msi".equalsIgnoreCase(extName)) {
+ typeName = "msi";
+ }
+ } else if ("zip".equals(typeName)) {
+ // zip可能为docx、xlsx、pptx、jar、war等格式,扩展名辅助判断
+ final String extName = FileUtil.extName(file);
+ if ("docx".equalsIgnoreCase(extName)) {
+ typeName = "docx";
+ } else if ("xlsx".equalsIgnoreCase(extName)) {
+ typeName = "xlsx";
+ } else if ("pptx".equalsIgnoreCase(extName)) {
+ typeName = "pptx";
+ } else if ("jar".equalsIgnoreCase(extName)) {
+ typeName = "jar";
+ } else if ("war".equalsIgnoreCase(extName)) {
+ typeName = "war";
+ }
+ }
+ return typeName;
}
/**
* 通过路径获得文件类型
- *
+ *
* @param path 路径,绝对路径或相对ClassPath的路径
* @return 类型
* @throws IORuntimeException 读取文件引起的异常
diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java
index cd72ad167..d12af648e 100644
--- a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java
@@ -1551,7 +1551,7 @@ public class FileUtil {
pathToUse = StrUtil.removePrefixIgnoreCase(pathToUse, URLUtil.FILE_URL_PREFIX);
// 识别home目录形式,并转换为绝对路径
- if(pathToUse.startsWith("~")){
+ if (pathToUse.startsWith("~")) {
pathToUse = pathToUse.replace("~", getUserHomePath());
}
@@ -1875,6 +1875,12 @@ public class FileUtil {
/**
* 根据文件流的头部信息获得文件类型
*
+ * + * 1、无法识别类型默认按照扩展名识别 + * 2、xls、doc、msi头信息无法区分,按照扩展名区分 + * 3、zip可能为docx、xlsx、pptx、jar、war头信息无法区分,按照扩展名区分 + *+ * * @param file 文件 {@link File} * @return 类型,文件的扩展名,未找到为
null
* @throws IORuntimeException IO异常
diff --git a/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java
index 64660fbdc..e8152ffec 100644
--- a/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java
@@ -781,23 +781,9 @@ public class IoUtil {
return toStream(content, CharsetUtil.CHARSET_UTF_8);
}
- /**
- * String 转为流
- *
- * @param content 内容bytes
- * @return 字节流
- * @since 4.1.8
- */
- public static ByteArrayInputStream toStream(byte[] content) {
- if (content == null) {
- return null;
- }
- return new ByteArrayInputStream(content);
- }
-
/**
* 文件转为流
- *
+ *
* @param file 文件
* @return {@link FileInputStream}
*/
@@ -809,6 +795,20 @@ public class IoUtil {
}
}
+ /**
+ * String 转为流
+ *
+ * @param content 内容bytes
+ * @return 字节流
+ * @since 4.1.8
+ */
+ public static ByteArrayInputStream toStream(byte[] content) {
+ if (content == null) {
+ return null;
+ }
+ return new ByteArrayInputStream(content);
+ }
+
/**
* 转换为{@link BufferedInputStream}
*
diff --git a/hutool-core/src/test/java/cn/hutool/core/io/FileTypeUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/io/FileTypeUtilTest.java
index 4ff554ab0..bd72925e4 100644
--- a/hutool-core/src/test/java/cn/hutool/core/io/FileTypeUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/io/FileTypeUtilTest.java
@@ -1,14 +1,11 @@
package cn.hutool.core.io;
-import java.io.File;
-
+import cn.hutool.core.lang.Console;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
-import cn.hutool.core.io.FileTypeUtil;
-import cn.hutool.core.io.FileUtil;
-import cn.hutool.core.lang.Console;
+import java.io.File;
/**
* 文件类型判断单元测试
@@ -36,4 +33,12 @@ public class FileTypeUtilTest {
String type = FileTypeUtil.getType(file);
Console.log(type);
}
+
+ @Test
+ @Ignore
+ public void docTest() {
+ File file = FileUtil.file("f:/test/test.doc");
+ String type = FileTypeUtil.getType(file);
+ Console.log(type);
+ }
}
diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellUtil.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellUtil.java
index 197104362..386253764 100644
--- a/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellUtil.java
+++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/cell/CellUtil.java
@@ -1,10 +1,9 @@
package cn.hutool.poi.excel.cell;
-import java.math.BigDecimal;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.List;
-
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.poi.excel.StyleSet;
+import cn.hutool.poi.excel.editors.TrimEditor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
@@ -13,13 +12,14 @@ import org.apache.poi.ss.usermodel.RichTextString;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.NumberToTextConverter;
import org.apache.poi.ss.util.RegionUtil;
import org.apache.poi.ss.util.SheetUtil;
-import cn.hutool.core.date.DateUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.poi.excel.StyleSet;
-import cn.hutool.poi.excel.editors.TrimEditor;
+import java.math.BigDecimal;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
/**
* Excel表格中单元格工具类
@@ -27,6 +27,7 @@ import cn.hutool.poi.excel.editors.TrimEditor;
* @author looly
* @since 4.0.7
*/
+@SuppressWarnings("deprecation")
public class CellUtil {
/**
@@ -283,26 +284,26 @@ public class CellUtil {
final double value = cell.getNumericCellValue();
final CellStyle style = cell.getCellStyle();
- if (null == style) {
- return value;
- }
+ if (null != style) {
+ final short formatIndex = style.getDataFormat();
+ // 判断是否为日期
+ if (isDateType(cell, formatIndex)) {
+ return DateUtil.date(cell.getDateCellValue());// 使用Hutool的DateTime包装
+ }
- final short formatIndex = style.getDataFormat();
- // 判断是否为日期
- if (isDateType(cell, formatIndex)) {
- return DateUtil.date(cell.getDateCellValue());// 使用Hutool的DateTime包装
- }
-
- final String format = style.getDataFormatString();
- // 普通数字
- if (null != format && format.indexOf(StrUtil.C_DOT) < 0) {
- final long longPart = (long) value;
- if (longPart == value) {
- // 对于无小数部分的数字类型,转为Long
- return longPart;
+ final String format = style.getDataFormatString();
+ // 普通数字
+ if (null != format && format.indexOf(StrUtil.C_DOT) < 0) {
+ final long longPart = (long) value;
+ if (((double) longPart) == value) {
+ // 对于无小数部分的数字类型,转为Long
+ return longPart;
+ }
}
}
- return value;
+
+ // 某些Excel单元格值为double计算结果,可能导致精度问题,通过转换解决精度问题。
+ return Double.parseDouble(NumberToTextConverter.toText(value));
}
/**
diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelReadTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelReadTest.java
index b909466db..fb12b0afc 100644
--- a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelReadTest.java
+++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelReadTest.java
@@ -190,4 +190,14 @@ public class ExcelReadTest {
return "Person [name=" + name + ", gender=" + gender + ", age=" + age + "]";
}
}
+
+ @Test
+ @Ignore
+ public void readDoubleTest(){
+ ExcelReader reader = ExcelUtil.getReader("f:/test/doubleTest.xls");
+ final List