java.io.FileNotFoundException与java.io.IOException

FileNotFoundException

开发背景:系统需添加一个云盘模块,有文件上传功能,同步上传大文件传输速度很慢,用户等待时间过长,采取了异步上传。发现有时存在系统找不到指定的文件,导致上传失败的问题。

发现问题:网络查找发现是springboot文件上传,会创建临时目录保存临时文件,处理完后会清除。

报错信息如下:

java.io.FileNotFoundException: C:\Users\***\work\Catalina\localhost\ROOT\upload_22e2506c_3d38_4755_8ea1_f81b600f8c2e_00000005.tmp (系统找不到指定的文件。)
	at java.io.FileInputStream.open0(Native Method)
	at java.io.FileInputStream.open(FileInputStream.java:195)
	at java.io.FileInputStream.<init>(FileInputStream.java:138)
	at org.apache.tomcat.util.http.fileupload.disk.DiskFileItem.getInputStream(DiskFileItem.java:194)
	at org.apache.catalina.core.ApplicationPart.getInputStream(ApplicationPart.java:100)
	at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile.getInputStream(StandardMultipartHttpServletRequest.java:296)
	at cn.com.teacher.service.impl.MyCloudStorageServiceImpl.saveFile(MyCloudStorageServiceImpl.java:75)
	at cn.com.teacher.service.impl.MyCloudStorageServiceImpl.lambda$saveCloudStorageFile$0(MyCloudStorageServiceImpl.java:64)
	at java.util.concurrent.CompletableFuture$AsyncRun.run$$$capture(CompletableFuture.java:1626)
	at java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

之前代码:

CompletableFuture.runAsync(()->{
    saveFile(MultipartFile);
},executor);

现在代码:

InputStream inputStream = multipartFile.getInputStream();
CompletableFuture.runAsync(()->{
    //传递流
    saveFile(inputStream);
},executor);

解决方案:改为传递流

IOException

出现地点:需要把文件上传到OSS上,流关闭,后面需生成文件的md5值,工具类,也需要InputStream,里面也把流关闭,出现了问题。

发现问题:InputStream只能读取一次,如果需要重复读取,需要转换或者存储。

报错信息:java.io.IOException: Stream Closed

解决方案:InputStream不支持重置,但是它的子类ByteArrayInputStream支持

    //InputStream代码

    public synchronized void mark(int readlimit) {}

   
    public synchronized void reset() throws IOException {
        throw new IOException("mark/reset not supported");
    }

    
    public boolean markSupported() {
        return false;
    }
    //ByteArrayInputStream代码
   
    protected int mark = 0;

    //是否支持重置
    public boolean markSupported() {
        return true;
    }

    //定点,下次从哪里重新读取
    public void mark(int readAheadLimit) {
        mark = pos;
    }

    //重置到定点位置后,可重新读取
    public synchronized void reset() {
        pos = mark;
    }

把InputStream转换未ByteArrayInputStream,第二次使用前使用重置方法即可

byteArrayInputStream.reset();

下面转换代码取自:InputStream重复使用小技巧_I_am_zz.的博客-CSDN博客_inputstream重复使用

public static ByteArrayInputStream toByteArrayInputStream(InputStream inputStream) throws IOException {
        if (inputStream instanceof ByteArrayInputStream) {
            return (ByteArrayInputStream) inputStream;
        }

        try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
            BufferedInputStream br = new BufferedInputStream(inputStream);
            byte[] b = new byte[1024];
            for (int c; (c = br.read(b)) != -1; ) {
                bos.write(b, 0, c);
            }
            // 主动告知回收
            b = null;
            br.close();
            inputStream.close();
            return new ByteArrayInputStream(bos.toByteArray());
        }
    }

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值