文件上传,断点续传操作

一、使用springmvc的上传

 // 使用transferTo
    public String upload(MultipartFile file) throws IOException {

        File dest = new File("E:\\test\\"+UUIDUtils.getUUID()+file.getName());
        if(dest.exists()){
            dest.createNewFile();
        }
        try {
            file.transferTo(dest);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("上传问题");
        }
        return "success";
    }

这是由springmvc自己分装的,也是最方便快捷的不需要关流什么的处理。

二、传统的输入输出流

 public String upload2(MultipartFile file) throws IOException {
        File dest = new File("E:\\test\\" + UUIDUtils.getUUID()+".txt");
        InputStream inputStream = file.getInputStream();
        OutputStream outputStream = new FileOutputStream(dest);
        try {
            IOUtils.copy(inputStream, outputStream);
        }catch (Exception e){
            e.getStackTrace();
        }
        finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return "success";
    }

也还ok,写起来没什么难度。就是异常处理比较多需要各种判断

三、这里讲一下字节流和字符流

   Java的流式输入输出建立在4个抽象类的基础上:InputStream,OutputStream,Reader和Writer。它们用来创建具体的流式子类。InputStream和OutputStream类被设计为字节类,而Reader和Writer被设计为字符流类。

  这里复制网上代码

FileInputStream读取的两种方法:逐字节读;以字节数组读取两种方式;

public static void main(String[] args) {
        //创建文件对象,指定要读取的文件路径(要读的文件一定要存在)
        File file=new File("E:\\a.text");
        
        try {
            //创建文件输入流对象.指定要读取的文件对象
            FileInputStream fin=new FileInputStream(file);
            
            /***********方法一(将输入流的数据传递给字节数组)*********/
            //创建字节数组,准备将文件流中的数据传给字节数组
            /*byte[] b=new byte[fin.available()];
            
            //将字节流中的数据传递给字节数组
            fin.read(b);
            
            //将字节数组转为字符串
            String s=new String(b);
            
            System.out.println(s);*/
            /*********************************************/
            
            /********方法二(逐字节读取数据从字节输入流)***********/
            int l;
            while ((l=fin.read())!=-1) {
                System.out.println((char)l);
                //测试read()方法的含义,什么是逐字节读,及int类型的l代表什么意思,测试结果l代表存储的内容的int的表现形式,与进制相关,不做深究
                //System.out.println((char)l+"\t"+l);
            }
            
            fin.close();
            /************************************************/
            
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

FileOutputStream写入文件的两种方式:以字节数组写入;逐字节写入;

public static void main(String[] args) {
        // TODO Auto-generated method stub
        //创建文件对象,指定要写出的文件路径
        File file=new File("d:\\d.text");
        
        try {
            //创建文件字节输出流对象,准备向d.txt文件中写出数据,true表示在原有的基础上增加内容
            FileOutputStream fout=new FileOutputStream(file,true);
            Scanner sc=new Scanner(System.in);
            
            System.out.println("请写出一段字符串:");
            String msg=sc.next()+"\r\n";;
            
            /******************(方法一)按字节数组写入**********************/
            //byte[] bytes = msg.getBytes();//msg.getBytes()将字符串转为字节数组
            
            //fout.write(bytes);//使用字节数组输出到文件
            /******************(方法一)逐字节写入**********************/
            byte[] bytes = msg.getBytes();
            for (int i = 0; i < bytes.length; i++) {
                fout.write(bytes[i]);//逐字节写文件
            }
            fout.flush();//强制刷新输出流
            fout.close();//关闭输出流
            System.out.println("写入完成!");
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

字节流转化为字符流

为什么将字节流转化为字符流?

因为字节流是二进制读写的,在外部打开是乱码,转化为字符串或字符可以让文件在外部也可以看到内容!根据具体的需求确定用哪个!

  //创建字节输出流对象
            FileOutputStream fout=new FileOutputStream(new File("student.xml"));
            //创建字节流缓冲区,加快写出速度
            BufferedOutputStream bout=new BufferedOutputStream(fout);
            
            //创建字符输出流对象
            BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(bout, "utf-8"));
            
            doc.write(bw);
            
            bw.flush();
            bw.close();

四、最后介绍一下最近写的业务,断点续传使用到的RandomAccessFile

1.先介绍一下

    我们可以看到它的父类是Object,没有继承字节流、字符流家族中任何一个类。并且它实现了DataInput、DataOutput这两个接口,也就意味着这个类既可以读也可以写。

2.为什么会存在?

(1)、是JAVA I/O流体系中功能最丰富的文件内容访问类,它提供了众多方法来访问文件内容。

(2)、由于可以自由访问文件的任意位置,所以如果需要访问文件的部分内容,RandomAccessFile将是更好的选择。

(3)、可以用来访问保存数据记录的文件,文件的记录的大小不必相同,但是其大小和位置必须是可知的。

这个读取文件和添加文字使用了一下发现并不是很好用。他还是适合断点续传,总是有乱码问题比较烦,我就拿网上的例子看一下

 public static void main(String[] args) {
        try {
            insert("e:/test/a.txt", 5, ("插入内容".getBytes("utf-8"))+"");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void insert(String fileName, long pos, String content) throws IOException {

        // 创建临时文件 prefix文件名 suffix文件后缀
        File tempFile = File.createTempFile("b", "txt",new File("E:\\test"));
        // 删除临时文件
        tempFile.delete();
        FileOutputStream fos = new FileOutputStream(tempFile);


        RandomAccessFile raf = new RandomAccessFile(fileName, "rw");
        raf.seek(pos);
        byte[] buffer = new byte[4];
        int num = 0;
        while (-1 != (num = raf.read(buffer))) {
            fos.write(buffer, 0, num);
        }
        raf.seek(pos);
        raf.write(content.getBytes());
        FileInputStream fis = new FileInputStream(tempFile);
        while (-1 != (num = fis.read(buffer))) {
            raf.write(buffer, 0, num);
        }
    }

讲一下断点续传用到的代码,断点续传具体逻辑和代码下次写

这里使用的是将排序好的文件合并成一个组合文件,上码

这里是最初的简单逻辑入参是空文件,和排好序的数组文件

 // 合并文件
    private File mergeFile(File mergeFile, List<File> chunkFiles) {

        // 将排序好的文件全部写入新创建的文件
        if (chunkFiles == null && mergeFile == null) {
            // 传入排序文件为空
            return null;
        }
        // 创建输入流和输出流
        try {
            RandomAccessFile random_write = new RandomAccessFile(mergeFile, "rw");
            byte[] b = new byte[1024];
            int len = -1;
            // 遍历文件数组
            for (File chunkFile : chunkFiles) {
                RandomAccessFile random_read = new RandomAccessFile(chunkFile, "r");
                while ((len = random_read.read(b)) != -1) {
                    random_write.write(b, 0, len);
                }
                random_read.close();
            }
            random_write.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return mergeFile;
    }

五、这里做一个总结

    根据需求来选择,只需要上传文件,最简单使用transferTo

  用空格真的难受......

InputStream OutputStream说实话没卵用还是就上传用吧。

如果上传完成要读取或者要检验文件的内容呢就用

 // 读取文件
    public List<TSysBatchWithhold> readFiles(String getPath, String getPartnerNo, String getFileBatchNo) throws SysException {

        List<TSysBatchWithhold> _list = new ArrayList<>();
        if (getPath == null || getPartnerNo == null || getFileBatchNo == null) {
           throw new SysException("空");
        }
        try {
            logger.info("=======读取文件开始===========");
            String encoding = "UTF-8";
            File file = new File(getPath);
            if (file.isFile() && file.exists()) {
                //判断文件是否存在
                InputStreamReader read = new InputStreamReader(
                        new FileInputStream(file), encoding);
                //编码格式
                BufferedReader bufferedReader = new BufferedReader(read);
                String lineTxt = null;
                TSysBatchWithhold tSysBatchWithhold = null;
                while ((lineTxt = bufferedReader.readLine()) != null) {
                    tSysBatchWithhold = new TSysBatchWithhold();
                    String uuid = UUIDUtils.getUUID();
                    logger.info("获取到的ID是:{}", uuid);
                    tSysBatchWithhold.setId(uuid);
                    tSysBatchWithhold.setPartnerNo(getPartnerNo);
                    tSysBatchWithhold.setBatchNo(getFileBatchNo);
                    tSysBatchWithhold.setStatus(BatchWithholdStatusEnum.INIT.getCode());
                    tSysBatchWithhold = dataCheckAndSave(lineTxt, tSysBatchWithhold);
                    _list.add(tSysBatchWithhold);
                    logger.info("读取每行数据" + lineTxt);
                }
                read.close();
            } else {
                throw new SysException("文件不存在");
            }
        } catch (SysException se) {
            throw se;
        } catch (Exception e) {
            throw new SysException("文件上传失败,请重新操作", e);
        }

        return _list;
    }

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值