偶尔发生File has been moved - cannot be read again,其实是个误解
使用poi上传.xlsx文件时,出现如下错误
Exception in thread "pool-3-thread-2" java.lang.IllegalStateException: File has been moved - cannot be read again
at org.springframework.web.multipart.commons.CommonsMultipartFile.getInputStream(CommonsMultipartFile.java:125)
at cn.dataenergy.stat.yxjlbj.web.JlpbbjController$1.run(JlpbbjController.java:200)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
注意该问题是偶尔发生,并非每次都能重现。而且发生的概率很低,但是一发生,可能连续多次导入都会爆同样的错。
第一感这应该是一个多线程问题,因为不是每次能重现很有可能是资源竞争。同时代码中也确实用了多线程.在我的controller中:
threadool.execute(new Runnable() {
@Override
public void run() {
try {
File tmpFile = new File(filepath);
InputStream inputStream = file.getInputStream();// 直接将文件读入到刘中
FileUtils.copyInputStreamToFile(inputStream, tmpFile);
Workbook wb = createworkbook(new FileInputStream(tmpFile));
tmpFile.delete();// 删除本地文件
String[] strExcelFlag = jlpbbjService.getExcelFlag(wb);
jlpbbjService.yxjlImportAndCompare(wb,
Integer.valueOf(strExcelFlag[1]), type,meterCompareTask);
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
出错的地方正是
file.getInputStream();// 直接将文件读入到刘中
这里。这里只帖上了关键的代码。上传文件的处理可能是很耗时的,所以新建了一个线程去做处理工作。
网上的资料均指向的一个问题
<beans:bean > <!--The limitation size of file is 500m。the value -1 means there is no limitation-->
<beans:property value="500000000"/> <beans:property value="500000000"/> </beans:bean>
在配置spring MultipartResolver时不仅要配置maxUploadSize,还需要配置maxInMemorySize。但原因都没说的很清楚。只是简单说maxInMemorySize的默认值为1024 bytes(待确认),超出这个大小的文件上传spring会先将上传文件记录到临时文件中。临时文件会被删除。
我其实不是很赞同这种说法,还有说如果要在系统中读文件两次,而文件不在内存中,就会导致该问题。(已证明其实可以多次读文件,只要是单线程即可),所以我认为原因并不是出在这里,但是对于是不是加了多线程就会出错,我更加不认可。
其实这个问题,网上有位作者做了深入的研究,但是我觉得他研究的毫无意义,因为他把注意力都放到了这个问题就是一个多线程上了。有兴趣的朋友可以去看看她的博客http://www.th7.cn/Program/java/201609/956455.shtml,其实不然。正真的问题不是出在这里,而是,不应该把无关紧要的代码放到线程当中,既然这个问题,有可能是多线造成的,那么我们可以换个思路,不要去针对多线程去解决问题,而是应该避免出现这样的问题,这时候,我就想到了吧无关的代码移除到线程外边,ok。问题果然再没有出现了。移出后的Controller代码为
File tmpFile = new File(filepath);
final InputStream inputStream = file.getInputStream();// 直接将文件读入到刘中
FileUtils.copyInputStreamToFile(inputStream, tmpFile);
final Workbook wb = createworkbook(new FileInputStream(tmpFile));
tmpFile.delete();// 删除本地文件
threadool.execute(new Runnable() {
@Override
public void run() {
String[] strExcelFlag = jlpbbjService.getExcelFlag(wb);
jlpbbjService.yxjlImportAndCompare(wb,
Integer.valueOf(strExcelFlag[1]), type,
meterCompareTask);
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
偶尔发生File has been moved - cannot be read again,其实是个误解的更多相关文章
- 云笔记项目- 上传文件报错"java.lang.IllegalStateException: File has been moved - cannot be read again"
在做文件上传时,当写入上传的文件到文件时,会报错“java.lang.IllegalStateException: File has been moved - cannot be read again ...
- File Operation using SHFileOperation
SHFILEOPSTRUCT Original link: http://winapi.freetechsecrets.com/win32/WIN32SHFILEOPSTRUCT.htm Refere ...
- JAVA FILE.renameTo跨文件系统移动文件失败
遇到了FILE.renameTo跨文件系统移动文件失败的问题,应使用FILES.move()接口或在同一文件系统移动文件. FILE.renameTo接口说明: public boolean rena ...
- CommonsMultipartFile 转为 File 类型
1.我们可以查看CommonsMultipartFile的源码发现有这样一个方法 @Override public InputStream getInputStream() throws IOExce ...
- LODOP中无规律无法还原偶尔出现问题排查
一些问题无法还原且偶尔出现,没法通过做例子来展示问题,为了找到问题在哪里,就需要排查定位问题 .由于这些问题偶尔出现,且无规律,出现频率低,所以只能不断通过各种对比测试,定位排查到问题和什么有关.如果 ...
- 一次部署HTTPS的相关事件引发的思考
前言: 上周五快要下班的时候,突然收到通知客户希望了解一下部署HTTPS的流程,这种事情谁听了都会有几分诧异的.因为这件事虽然和工作有一定的相关度,但平时不会走这个方向,实际上也较少接触.此外,客户手 ...
- 基于Yahoo网站性能优化的34条军规及自己的见解
1.尽量减少HTTP请求次数 终端用户响应的时间中,有80%用于下载各项内容,这部分时间包括下载页面中的图像.样式表.脚本.Flash等.通过减少页面中的元素可以减少HTTP请求的次数,这是提高网页速 ...
- inotifywait命令
[命令格式]: inotifywait [ options ] file1 [ file2 ] [ file3 ] [ ... ][命令原意]: inote file system wait[命令路径 ...
- 【转】怎样查出SQLServer的性能瓶颈
怎样查出SQLServer的性能瓶颈 --王成辉翻译整理,转贴请注明出自微软BI开拓者[url]www.windbi.com[/url]--原帖地址 如果你曾经做了很长时间的DBA,那么你会了解到SQ ...
随机推荐
- MySQL只恢复某个库或某张表
在Mysqldump官方工具中,如何只恢复某个库呢? 全库备份 [root@HE1 ~]#mysqldump -uroot -p --single-transaction -A --master-da ...
- VAST3.0规范
VAST3.0视频广告投放规范 Posted on 2014年2月15日 1.术语 随着视频广告行业的发展,某些术语已经得到了广泛的采用.以下定义该文档中与视频广告投放相关的一些术语: 广告荚(Ad ...
- Java 字符终端上获取输入三种方式
http://blog.csdn.net/hongweigg/article/details/14448731 在Java 字符终端上获取输入有三种方式: 1.java.lang.System.in ...
- Sql Server 查询多行并一行
干货 CREATE TABLE #benefit_code21 (id INT, number nvarchar(MAX), pname ), collegeID INT, applicationda ...
- java算法 蓝桥杯 高精度加法
问题描述 在C/C++语言中,整型所能表示的范围一般为-231到231(大约21亿),即使long long型,一般也只能表示到-263到263.要想计算更加规模的数,就要用软件来扩展了,比如用数组或 ...
- python中关于局部变量与全局变量的认识
1.函数内部的变量名如果第一次出现,且出现在=前面,即被视为定义一个局部变量,不管全局域中有没有用到该变量名,函数中使用的将是局部变量,例如: num = 100 def func(): num = ...
- 2017《JAVA技术》预备作业
1.阅读邹欣老师的博客,谈谈你期望的师生关系是什么样的? ==我期望的师生关系是长辈和晚辈,前辈和后生,朋友与朋友之间的关系,作为晚辈,要尊敬长辈,不能对长辈进行言语攻击和起冲突:作为后生,要谨遵教诲 ...
- UOJ #278. 【UTR #2】题目排列顺序(排序水题)
#278. [UTR #2]题目排列顺序 丢个传送门:http://uoj.ac/problem/278 描述 “又要出题了.” 宇宙出题中心主任 —— 吉米多出题斯基,坐在办公桌前策划即将到来的 U ...
- jquery 高级 学习笔记
--jquery 和 原生js可以共存,但不能混用.jquery 可以通过get()方法 转换为原生js. $("#div1").get(0).innerHTML; get() 需 ...
- block之---应用场景:做参数和返回值
1.做参数 什么时候使用Block充当参数? 封装一个功能,这个功能做什么事情由外界决定,但是什么时候调用由内部决定,这时候就需要把Block充当参数去使用. 模拟需求: 封装一个计算器,怎么计算由外 ...