fix double bug

This commit is contained in:
Looly 2019-11-09 17:35:38 +08:00
parent b5297bd7e6
commit a3b3743f3f
7 changed files with 122 additions and 64 deletions

View File

@ -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的bugissue#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
-------------------------------------------------------------------------------------------------------------

View File

@ -11,13 +11,12 @@ import cn.hutool.core.util.StrUtil;
/**
* 文件类型判断工具类
*
* <p>此工具根据文件的前几位bytes猜测文件类型对于文本zip判断不准确对于视频图片类型判断准确</p>
*
* <p>需要注意的是xlsxdocx等Office2007格式全部识别为zip因为新版采用了OpenXML格式这些格式本质上是XML文件打包为zip</p>
*
* @author Looly
*
* <p>此工具根据文件的前几位bytes猜测文件类型对于文本zip判断不准确对于视频图片类型判断准确</p>
*
* <p>需要注意的是xlsxdocx等Office2007格式全部识别为zip因为新版采用了OpenXML格式这些格式本质上是XML文件打包为zip</p>
*
* @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 注意wordmsi 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 注意wordmsi 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 {
/**
* 增加文件类型映射<br>
* 如果已经存在将覆盖之前的映射
*
*
* @param fileStreamHexHead 文件流头部Hex信息
* @param extName 文件扩展名
* @param extName 文件扩展名
* @return 之前已经存在的文件扩展名
*/
public static String putFileType(String fileStreamHexHead, String extName) {
@ -90,7 +89,7 @@ public class FileTypeUtil {
/**
* 移除文件类型映射
*
*
* @param fileStreamHexHead 文件流头部Hex信息
* @return 移除的文件扩展名
*/
@ -100,13 +99,13 @@ public class FileTypeUtil {
/**
* 根据文件流的头部信息获得文件类型
*
*
* @param fileStreamHexHead 文件流头部16进制字符串
* @return 文件类型未找到为<code>null</code>
*/
public static String getType(String fileStreamHexHead) {
for (Entry<String, String> fileTypeEntry : fileTypeMap.entrySet()) {
if(StrUtil.startWithIgnoreCase(fileStreamHexHead, fileTypeEntry.getKey())) {
if (StrUtil.startWithIgnoreCase(fileStreamHexHead, fileTypeEntry.getKey())) {
return fileTypeEntry.getValue();
}
}
@ -115,7 +114,7 @@ public class FileTypeUtil {
/**
* 根据文件流的头部信息获得文件类型
*
*
* @param in {@link InputStream}
* @return 类型文件的扩展名未找到为<code>null</code>
* @throws IORuntimeException 读取流引起的异常
@ -126,24 +125,59 @@ public class FileTypeUtil {
/**
* 根据文件流的头部信息获得文件类型
*
*
* <pre>
* 1无法识别类型默认按照扩展名识别
* 2xlsdocmsi头信息无法区分按照扩展名区分
* 3zip可能为docxxlsxpptxjarwar头信息无法区分按照扩展名区分
* </pre>
*
* @param file 文件 {@link File}
* @return 类型文件的扩展名未找到为<code>null</code>
* @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)) {
// xlsdocmsi的头一样使用扩展名辅助判断
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可能为docxxlsxpptxjarwar等格式扩展名辅助判断
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 读取文件引起的异常

View File

@ -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 {
/**
* 根据文件流的头部信息获得文件类型
*
* <pre>
* 1无法识别类型默认按照扩展名识别
* 2xlsdocmsi头信息无法区分按照扩展名区分
* 3zip可能为docxxlsxpptxjarwar头信息无法区分按照扩展名区分
* </pre>
*
* @param file 文件 {@link File}
* @return 类型文件的扩展名未找到为<code>null</code>
* @throws IORuntimeException IO异常

View File

@ -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}
*

View File

@ -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);
}
}

View File

@ -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));
}
/**

View File

@ -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<List<Object>> read = reader.read();
for (List<Object> list : read) {
Console.log(list.get(8));
}
}
}