Java文件断点续传

这篇具有很好参考价值的文章主要介绍了Java文件断点续传。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Java文件断点续传

断点续传实现思路:将大文件均分成几块后,每个线程分别处理一块数据的读取和写入。每次写入都要更新记录的日志文件,断网或暂定后重新开始传输时,根据日志文件的信息,可以接着读取写入数据,不用重头开始传输。文章来源地址https://www.toymoban.com/news/detail-519652.html

package com.demo;

import java.io.*;
import java.time.Duration;
import java.time.Instant;
import java.util.Map;
import java.util.StringJoiner;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;

/**
 * @descpription: 文件断点续传
 * @date 2023/3/4
 */
public class RandomAccessFileDemo {

    /**
     * 指定线程数
     */
    private static final Integer THREAD_NUM = 2;

    public static void main(String[] args) {
        String sourceStr = "~/Downloads/视频/视频.zip";
        String targetStr = "~/Desktop/视频123.zip";
        breakpointResume(sourceStr,targetStr);
    }

    /**
     * 断点续传
     *
     * @param sourceStr   目标文件地址
     * @param targetStr 存放地址
     */
    public static void breakpointResume(String sourceStr, String targetStr) {
        File dataFile = new File(sourceStr);
        long length = dataFile.length();
        //每个线程均分文件大小,且向上取整
        long part = (long) Math.ceil(length / THREAD_NUM);
        //线程减法计数器
        CountDownLatch countDownLatch = new CountDownLatch(THREAD_NUM);
        Instant beginTime = Instant.now();
        //记录传输的日志文件
        File logFile = new File(targetStr + ".log");
        String[] splitData = null;//不是null就需要断点续传
        BufferedReader reader = null;
        try {
            if (logFile.exists()) {
                //存在日志文件,需要进行断点续传
                reader = new BufferedReader(new FileReader(logFile));
                String data = reader.readLine();
                splitData = data.split(",");
            } else {
                //不存在日志文件,创建日志文件
                logFile.createNewFile();
            }
            Map<Integer, Long> maps = new ConcurrentHashMap<>();
            for (int i = 0; i < THREAD_NUM; i++) {
                final int k = i;
                System.out.println("线程正在执行任务:" + k);
                String[] finalData = splitData;
                new Thread(() -> {
                    RandomAccessFile inFile = null;
                    RandomAccessFile outFile = null;
                    RandomAccessFile rafLog = null;
                    try {
                        inFile = new RandomAccessFile(dataFile, "r");//读
                        outFile = new RandomAccessFile(targetStr, "rw");//写
                        rafLog = new RandomAccessFile(logFile, "rw");//操作日志文件的流
                        //确定每个线程读取文件的开始和结束的位置,有断点续传就从日志文件取出的位置开始读取
                        inFile.seek(finalData == null ? k * part : Long.parseLong(finalData[k]));//设置每个线程读取的启始位置
                        outFile.seek(finalData == null ? k * part : Long.parseLong(finalData[k]));//设置每个线程写入的启始位置
                        byte[] bytes = new byte[1024 * 10];//每次读取字节大小
                        int len = -1, allLen = 0;
                        while (true) {
                            len = inFile.read(bytes);//从磁盘读取到缓存
                            if (len == -1) { //数据读完,结束
                                break;
                            }
                            //如果不等于 -1,把每次读取的字节累加
                            allLen = allLen + len;
                            //将读取的字节数放入到map中
                            maps.put(k, allLen + (finalData == null ? k * part : Long.parseLong(finalData[k])));//每个线程的绝对偏移量
                            outFile.write(bytes, 0, len);//从缓存写入到磁盘
                            //将map中的字节日志信息数据写入磁盘
                            StringJoiner stringJoiner = new StringJoiner(",");
                            maps.forEach((key, value) -> stringJoiner.add(String.valueOf(value)));
                            //将日志信息写入磁盘
                            rafLog.seek(0);//覆盖之前的日志信息
                            rafLog.write(stringJoiner.toString().getBytes("UTF-8"));
                            /**
                             * 当前线程读取的内容
                             *  allLen + (k * part)
                             *  或
                             *  allLen + finalData[k] 日志文件里面的偏移量
                             *  >=
                             *  下个线程的起始部分((k + 1) * part)
                             *  当前线程就不再读取写入数据,结束任务
                             */
                            if (allLen + (finalData == null ? k * part : Long.parseLong(finalData[k])) >= (k + 1) * part) {
                                break;
                            }
                        }

                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        //关流
                        if (null != outFile && null != inFile && null != rafLog) {
                            try {
                                outFile.close();
                                inFile.close();
                                rafLog.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                        countDownLatch.countDown();//减一
                    }
                }).start();
            }

            //主线程要等到线程计数器归零,再继续往下执行
            countDownLatch.await();
            Instant endTime = Instant.now();
            System.out.println("总耗时:" + (Duration.between(beginTime, endTime).toMillis()) + "毫秒");
            //删除日志文件
            logFile.delete();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != reader) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

到了这里,关于Java文件断点续传的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 大文件切片上传+断点续传解决方案-前后端实现(附源码)

    上传文件大家应该都做过,前端直接把file文件传给后端就ok了,但是大文件这样传就会造成页面假死,体验极差。如果遇到网络不稳定的时候,中途上传失败的话,又要从头开始传,本来文件就大,还慢。所以今天我们用一种新方法-切片上传+断点续传 页面上很简单,我就放

    2024年02月09日
    浏览(47)
  • Vue项目中大文件切片上传实现秒传、断点续传的详细实现教程

    在Vue项目中,大图片和多数据Excel等大文件的上传是一个非常常见的需求。然而,由于文件大小较大,上传速度很慢,传输中断等问题也难以避免。因此,为了提高上传效率和成功率,我们需要使用切片上传的方式,实现文件秒传、断点续传、错误重试、控制并发等功能,并

    2024年02月12日
    浏览(77)
  • 【SpringBoot整合系列】SpringBoot 实现大文件分片上传、断点续传及秒传

    小文件(图片、文档、视频)上传可以直接使用很多ui框架封装的上传组件,或者自己写一个input 上传,利用FormData 对象提交文件数据,后端使用spring提供的MultipartFile进行文件的接收,然后写入即可。 但是对于比较大的文件,比如上传2G左右的文件(http上传),就需要将文件

    2024年04月16日
    浏览(67)
  • javaScript实现客户端直连华为云OBS实现文件上传、断点续传、断网重传

    写在前面:在做这个调研时我遇到的需求是前端直接对接华为云平台实现文件上传功能。上传视频文件通常十几个G、客户工作环境网络较差KB/s,且保证上传是稳定的,支持网络异常断点重试、文件断开支持二次拖入自动重传等。综合考虑使用的华为云的分段上传功能,基于

    2024年02月20日
    浏览(42)
  • 【前端面试】中大文件上传/下载:中等文件代理服务器放行+大文件切片传输+并发请求+localstorage实现断点续传

    目录 切片上传~spark-md5 原理:流式计算+分块处理 文件标识spark-md5:A-B A.切片哈希值合并 B.首尾切片+其他切片前中后各取2M 计算hash:A-B(参考React的Fiber架构) A.线程:web-worker B.空闲:requestIdleCallback 异步并发控制:A-B(参考http2的多路复用) A.promise.allSettled() B.并发数max=

    2024年02月12日
    浏览(56)
  • minio&前后端分离上传视频/上传大文件——前后端分离断点续传&minio分片上传实现

    🍀🍀🍀🍀分布式文件系统-minio: 第一章:分布式文件系统介绍与minio介绍与使用(附minio java client 使用) 第二章:minio前后端分离上传视频/上传大文件——前后端分离断点续传minio分片上传实现 断点续传指的是在下载或上传时,将下载或上传任务(一个文件或一个压缩包

    2024年02月03日
    浏览(55)
  • Spring Boot实现HTTP大文件断点续传分片下载-大视频分段渐进式播放

    服务端如何将一个大视频文件做切分,分段响应给客户端,让浏览器可以渐进式地播放。 Spring Boot实现HTTP分片下载断点续传,从而实现H5页面的大视频播放问题,实现渐进式播放,每次只播放需要播放的内容就可以了,不需要加载整个文件到内存中。 文件的断点续传、文件多

    2024年02月14日
    浏览(75)
  • U3D客户端框架之支持断点续传的文件下载器实现方案

            文件下载器是应用程序的基础模块,为应用程序与外部网络交互提供了必要的桥梁。该模块设计初衷是为了热更新过程中,下载CDN站点上的文件资源,所以下载器会验证 要下载的文件是否存在于CDN中。如果存在允许下载器继续工作;如果不存在会跳过本地下载。

    2024年02月07日
    浏览(55)
  • Spring-Boot实现HTTP大文件断点续传分片下载-大视频分段渐进式播放

    服务端如何将一个大视频文件做切分,分段响应给客户端,让浏览器可以渐进式地播放。 Spring Boot实现HTTP分片下载断点续传,从而实现H5页面的大视频播放问题,实现渐进式播放,每次只播放需要播放的内容就可以了,不需要加载整个文件到内存中。 文件的断点续传、文件多

    2024年02月11日
    浏览(56)
  • 【万字长文】Vue+SpringBoot实现大文件秒传、断点续传和分片上传完整教程(提供Gitee源码)

    前言:最近在实际项目中碰到一个需求,客户可能会上传比较大的文件,如果采用传统的文件上传方案可能会存在服务器压力大、资源浪费甚至内存溢出的一些安全风险,所以为了解决一系列问题,需要采用新的技术方案来实现大文件的上传;空闲的时候参考了网上的一些相

    2024年02月12日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包