分片下载、断点续传利器 - RandomAccessFile

   RandomAccessFile 是 Java 中提供的一个类,用于在文件中进行随机访问读写操作。它允许在文件的任意位置进行读写,可以用于实现断点续传和分片下载等功能。

  • RandomAccessFile(String name, String mode)
  • RandomAccessFile(File file, String mode)

name 或 file:文件的路径或 File 对象。
mode:文件的访问模式(r:只读、rw:读写)

常用方法

long length():返回文件的长度(字节数)。
void setLength(long newLength):设置文件长度。
long getFilePointer():返回当前文件指针的位置。
void seek(long pos):将文件指针设置到指定位置。
int read():读取一个字节,返回字节值或 -1(文件末尾)。
int read(byte[] b, int off, int len):读取字节到数组,返回读取字节数。
void write(int b):写入一个字节。
void write(byte[] b, int off, int len):写入字节数组。
void close():关闭文件并释放资源

使用示例

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

public class RandomAccessFileExample {

    public static void main(String[] args) {
        File file = new File("example.txt");

        try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
            // 写入数据
            raf.write("Hello, World!".getBytes());

            // 获取文件长度
            long fileLength = raf.length();
            System.out.println("File Length: " + fileLength);

            // 移动文件指针到开头
            raf.seek(0);

            // 读取数据
            byte[] buffer = new byte[(int) fileLength];
            raf.read(buffer);

            // 打印读取的数据
            System.out.println("Read Content: " + new String(buffer));

            // 在文件末尾追加数据
            raf.seek(fileLength);
            raf.write(" Goodbye!".getBytes());

            // 再次读取整个文件
            raf.seek(0);
            byte[] newBuffer = new byte[(int) raf.length()];
            raf.read(newBuffer);

            System.out.println("Updated Content: " + new String(newBuffer));

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

断点续传

断点续传是指在下载中断后,继续从上次中断的地方开始下载。RandomAccessFile 可以通过设置文件指针来实现这一功能。

实现步骤

  1. 记录下载进度:每次下载时记录已下载的字节数。
  2. 恢复下载:断点续传时,打开文件并将指针移动到上次下载结束的位置。
  3. 继续下载:从文件指针位置开始继续写入数据。

示例代码

public void resumeDownload(String fileURL, String localFilePath, int startByte) throws IOException {
    HttpURLConnection connection = (HttpURLConnection) new URL(fileURL).openConnection();
    connection.setRequestProperty("Range", "bytes=" + startByte + "-");

    try (InputStream inputStream = connection.getInputStream();
         RandomAccessFile raf = new RandomAccessFile(localFilePath, "rw")) {
        raf.seek(startByte);

        byte[] buffer = new byte[4096];
        int bytesRead;
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            raf.write(buffer, 0, bytesRead);
        }
    }
}

分片处理

分片处理是一种将大文件分成多个小块并行下载的技术,利用 RandomAccessFile 可以在不同位置写入数据,实现分片下载。

实现步骤

  1. 计算分片大小:根据文件总大小和线程数计算每个分片的大小。
  2. 多线程下载:为每个分片启动一个线程,设置文件指针到分片起始位置。
  3. 合并文件:下载完成后,所有分片自动合并到一个文件中。

示例代码

public void downloadFileWithChunks(String fileURL, String localFilePath, int threadCount) throws IOException {
    HttpURLConnection connection = (HttpURLConnection) new URL(fileURL).openConnection();
    int fileSize = connection.getContentLength();
    connection.disconnect();

    File file = new File(localFilePath);
    RandomAccessFile raf = new RandomAccessFile(file, "rw");
    raf.setLength(fileSize);
    raf.close();

    int chunkSize = fileSize / threadCount;
    ExecutorService executor = Executors.newFixedThreadPool(threadCount);

    for (int i = 0; i < threadCount; i++) {
        int startByte = i * chunkSize;
        int endByte = (i == threadCount - 1) ? fileSize : startByte + chunkSize - 1;

        executor.execute(new DownloadChunk(fileURL, localFilePath, startByte, endByte));
    }

    executor.shutdown();
    while (!executor.isTerminated()) {
        // 等待所有线程完成
    }

    System.out.println("Download completed successfully!");
}

static class DownloadChunk implements Runnable {
    private final String fileURL;
    private final String localFilePath;
    private final int startByte;
    private final int endByte;

    public DownloadChunk(String fileURL, String localFilePath, int startByte, int endByte) {
        this.fileURL = fileURL;
        this.localFilePath = localFilePath;
        this.startByte = startByte;
        this.endByte = endByte;
    }

    @Override
    public void run() {
        try {
            HttpURLConnection connection = (HttpURLConnection) new URL(fileURL).openConnection();
            connection.setRequestProperty("Range", "bytes=" + startByte + "-" + endByte);

            InputStream inputStream = connection.getInputStream();
            RandomAccessFile raf = new RandomAccessFile(localFilePath, "rw");
            raf.seek(startByte);

            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                raf.write(buffer, 0, bytesRead);
            }

            raf.close();
            inputStream.close();
            connection.disconnect();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

注意事项

  • 服务器支持:确保服务器支持 HTTP Range 请求。
  • 资源管理:使用 try-with-resources 确保文件流正确关闭。
  • 错误处理:在实际应用中需要处理网络异常、文件权限等问题。
  • 线程数选择:根据网络和服务器条件合理选择线程数。

通过以上方法,RandomAccessFile 可以有效地用于实现复杂的文件操作,如断点续传和分片下载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/921141.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024ARM网络验证 支持一键云注入引流弹窗注册机 一键脱壳APP加固搭建程序源码及教程

此套源码功能强大&#xff0c;支持APK脱壳、注入、网络验证、注册机、引流弹窗、更新弹窗和公告等功能&#xff0c;并具有强大的系统应用管理端&#xff0c;可轻松管理用户数量和卡密状态等数据统计。armpro脱壳软件可在线修改手机文件和游戏数据&#xff0c;并可添加会员功能、…

汉诺塔(hanio)--C语言函数递归

文章目录 前言一、汉诺塔的图解二、问题分析总结 前言 什么是汉诺塔&#xff1f; 汉诺塔(Tower of Hanoi)&#xff08;也称河内塔&#xff09;是有法国数学家爱德华卢卡斯于1883年发明的一道智力题。它源于印度的一个古老传说&#xff1a;大梵天创造世界的时候做了三根钻石柱子…

【MySQL】数据库精细化讲解:内置函数知识穿透与深度学习解析

前言&#xff1a;本节内容讲述mysql里面的函数的概念&#xff0c; 在mysql当中&#xff0c; 内置了很多函数工作。 这些函数丰富了我们的操作。 比如字符串函数、数据函数以及一些其他函数等等。 ps:友友们学习了表的基本操作后就可以观看本节内容啦! 目录 日期函数 current_…

Is:cannat access /data: Input/output error

说明&#xff1a; 1&#xff09;访问应用业务&#xff0c;输入账号密码报如下图所示&#xff1a;invalid login. 2&#xff09;登录服务器查看数据日志&#xff0c;报如下图所示&#xff1a;ls:cannot access /data: Input/output error 3&#xff09;查看日志dmesg |grep erro…

Python MySQL SQLServer操作

Python MySQL SQLServer操作 Python 可以通过 pymysql 连接 MySQL&#xff0c;通过 pymssql 连接 SQL Server。以下是基础操作和代码实战示例&#xff1a; 一、操作 MySQL&#xff1a;使用 pymysql python 操作数据库流程 1. 安装库 pip install pymysql2. 连接 MySQL 示例 …

迅为RK3562开发板直连电脑配置方法(无线上网)

概述 由于环境限制&#xff0c;笔记本电脑和开发板无法通过路由器连接起来&#xff0c;所以本文的目的是要实现笔记本电脑和虚拟机能够通过 WIFI 上网&#xff0c;并且开发板通过网线连接笔记本电脑和虚拟机在同一个网段内&#xff0c;最终实现 TFTP 或 NFS 来进行开发调试。 通…

Mono Repository方案与ReactPress的PNPM实践

ReactPress Github项目地址&#xff1a;https://github.com/fecommunity/reactpress 欢迎Star。 Mono Repository方案与ReactPress的PNPM实践 在当今软件开发领域&#xff0c;Mono Repository&#xff08;简称Monorepo&#xff09;已成为一种流行的代码管理方式&#xff0c;特…

timedatectl命令修改时间和时区

1.默认情况下&#xff0c;Linux系统通常每64分钟进行一次NTP时间同步。但是&#xff0c;这可以通过编辑/etc/ntp.conf文件来修改。在/etc/ntp.conf中设置minpoll和maxpoll参数。 timedatectl可以用来查询和更改系统时间设定&#xff0c;同时可以设定和修改时区信息。 一、查…

基于Opencv的图像处理软件

目录 一、背景及意义介绍背景意义 二、概述一、背景及意义介绍背景意义 三、论文思路解决问题 四、复现过程&#xff08;一&#xff09;图像处理模块二&#xff09;图形界面模块&#xff08;一&#xff09;图像处理模块实现步骤&#xff08;二&#xff09;图形界面模块实现步骤…

HTML的自动定义倒计时,这个配色存一下

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>自定义倒计时</title><style>* {mar…

私有化部署视频平台EasyCVR宇视设备视频平台如何构建视频联网平台及升级视频转码业务?

在当今数字化、网络化的时代背景下&#xff0c;视频监控技术已广泛应用于各行各业&#xff0c;成为保障安全、提升效率的重要工具。然而&#xff0c;面对复杂多变的监控需求和跨区域、网络化的管理挑战&#xff0c;传统的视频监控解决方案往往显得力不从心。 EasyCVR视频融合云…

MacOS通过X11转发远程运行virt-manager进行虚机分配

今天需要通过本地macbook机器连接远程物理机&#xff0c;执行虚机分配&#xff0c;现有文档仅提供window环境安装&#xff0c;如下整理Mac环境下的安装步骤 操作篇 前提条件 支持x11转发的terminal&#xff0c;我本地使用iTerm2&#xff1b;本地安装XQuartz&#xff0c;作为…

【每天学点AI】实战图像增强技术在人工智能图像处理中的应用

图像增强&#xff08;Image Enhancement&#xff09;是人工智能和计算机视觉中一项重要的技术&#xff0c;也是人工智能数据集预处理的一个重要步骤。它旨在提高图像的质量&#xff0c;使其在视觉上更加清晰、细节更丰富。这项技术在自动驾驶、医疗诊断、安防监控等领域有着广泛…

hbase mongodb hive starrocks比较

本文是在学习大数据的几个数据存储系统相关的组件所记录下来的&#xff0c;主要是不同组件的基础概念初步了解与对比。 NoSql 在大数据时代&#xff0c;虽然RDBMS很优秀&#xff0c;但是面对快速增长的数据规模和日渐复杂的数据模型&#xff0c;RDBMS渐渐力不从心&#xff0c…

STM32端口模拟编码器输入

文章目录 前言一、正交编码器是什么&#xff1f;二、使用步骤2.1开启时钟2.2配置编码器引脚 TIM3 CH1(PA6) CH2 (PA7)上拉输入2.3.初始化编码器时基2.4 初始化编码器输入2.5 配置编码器接口2.6 开启定时器2.7获取编码器数据 三、参考程序四、测试结果4.1测试方法4.2串口输出结果…

wireshark使用lua解析自定义协议

wireshark解析自定义协议 1.自定义的lua放入路径2.修改init.lua2.1 开启lua2.2 init.lua文件最后加入自己的lua文件位置&#xff0c;这里需要确保与自己的文件名相同 3.编写lua4.编写c抓包5.wireshark添加自定义协议如何加调试信息 1.自定义的lua放入路径 一般是自己软件的安装…

基于docker进行任意项目灵活发布

引言 不管是java还是python程序等&#xff0c;使用docker发布的优势有以下几点&#xff1a; 易于维护。直接docker命令进行管理&#xff0c;如docker stop、docker start等&#xff0c;快速方便无需各种进程查询关闭。环境隔离。项目代码任何依赖或设置都可以基本独立&#x…

友思特新闻 | 友思特荣获广州科技创新创业大赛智能装备行业赛初创组优胜企业!

2024年11月19日&#xff0c;第十三届中国创新创业大赛&#xff08;广东广州赛区&#xff09;暨2024年广州科技创新创业大赛智能装备行业赛颁奖典礼隆重举行。 赛事奖项介绍&#xff1a;广州科技创新创业大赛智能装备行业赛 第十三届“中国创新创业大赛&#xff08;广东广州赛区…

FreeRTOS——消息队列

目录 一、概念及其作用 1.1概念 1.2特点 1.3工作原理 二、相关API 2.1创建队列 2.2任务中写队列 2.3任务中读队列 2.4中断中写队列 2.5中断中读队列 三、实现原理 3.1消息队列控制块 3.2消息队列的创建 3.3消息的发送 3.3.1任务中发送 3.3.2中断中发送 3.4消息的…

11 —— 打包模式的应用

需求&#xff1a;在开发模式下想让webpack使用style-loader进行css样式的处理&#xff1b;让它把css代码内嵌在js中&#xff1b;在生产模式下提取css代码 —— 判断当前运行命令时所在的环境 方案&#xff1a;借助cross-env全局软件包&#xff0c;设置参数区分打包运行环境 …