1:编写一个测试文件分块的接口
定义一个File类型的变量sourceFile接收用File类读取要分块的文件
File sourceFile=new File("D:/Download/upload-video/变形金刚视频剪辑素材.mp4");
定义一个路径存储分块后的小文件
String chunkPath="D:/Download/upload-video/chunk/";
指定分块文件的大小(此处为5M;补充:
计算机默认情况下最小的存储单位是字节(byte); 1M=1024K;1K=1024byte(字节);1byte=8bit(比特);即1024byte*1024byte=1M
分块大小:表示定义了一个 long 类型的变量 chunkSize,其值为 1024*1024*5,即 5MB。
)
long chunkSize=1024*1024*5;
计算将要分块文件的分块总数(
计算需要分成多少块:分块数量(必须向上取整,避免分块有小数,小数被舍去,导致文件分块丢失)
)
long chunkNum=(long)Math.ceil(sourceFile.length()*1.0/chunkSize);
建立字节数组,用于缓存从源文件读取的数据:缓冲区大小1kb
byte[] b=new byte[1024];
使用RandomAccessFile来实现快速随机访问文件,以只读方式打开源文件
/**
* - 构造方法:RandomAccessFile(String name, String mode),用于创建RandomAccessFile对象,其中name为文件名,mode为文件打开模式("r"表示只读,"rw"表示读写)。
* - seek(long pos)方法:用于将文件指针移动到指定位置。
* - read()方法:用于读取一个字节。
* - read(byte[] b)方法:用于读取一定数量的字节到一个字节数组中。
* - write(int b)方法:用于写入一个字节。
* - write(byte[] b)方法:用于写入一个字节数组。
* */
RandomAccessFile raf_read=new RandomAccessFile(sourceFile,"r");
// 循环处理每个分块:使用for循环将待分块的文件分成多个小文件。
for(int i=0;i<chunkNum;i++){
// 根据序号创建新的块文件:首先创建一个File对象,指向分块后的文件目录 补充:Java中有自动类型转换的机制。在这里,Java会将int类型的i自动转换为String类型,所以chunkPath+i是它是 chunkPath 和 i 的拼接结果。不会出现报错
File file=new File(chunkPath+i);
if (file.exists()){
// 如果块文件已经存在,先删除。然后在本地磁盘上创建该目录
file.delete();
}
// 创建新的块文件:创建这个分块文件(理解为只有文件名的空文件)
boolean newFile=file.createNewFile();
// 如果成功创建新文件,则开始向其中写入数据
if (newFile){
// 创建一个RandomAccessFile对象raf_write,用于写入分块后的文件。
RandomAccessFile raf_write=new RandomAccessFile(file,"rw");
int len=-1;
// 使用while循环读取待分块的文件
while ((len=raf_read.read(b))!=-1){
// 将读取到的数据写入分块后的文件中
raf_write.write(b,0,len);
// 直到该文件的大小达到chunkSize即1M
if (file.length()>=chunkSize){
break;
}
}
raf_write.close();
System.out.println("完成分块"+i);
}
}
完整代码:
// 测试文件分块方法
@Test
public void testChunk() throws IOException{
// 创建了一个名为sourceFile的文件对象,这个对象可以用于读取或操作指定的文件,这里的sourceFile对象指向本地磁盘上的待分块文件。
File sourceFile=new File("D:/Download/upload-video/transform.mp4");
// 分块后的文件存储路径
String chunkPath="D:/Download/upload-video/chunk/";
File chunkFile=new File(chunkPath);
if (!chunkFile.exists()){
// 如果文件不存在就创建这个文件
chunkFile.mkdir();
}
// 提示:计算机默认情况下最小的存储单位是字节(byte); 1M=1024K;1K=1024byte(字节);1byte=8bit(比特);即1024byte*1024byte=1M
// 分块大小:表示定义了一个 long 类型的变量 chunkSize,其值为 1024*1024*5,即 5MB。
long chunkSize=1024*1024*5;
//计算需要分成多少块:分块数量(必须向上取整,避免分块有小数,小数被舍去,导致文件分块丢失)
//Math.ceil() 函数用于向上取整,确保结果不包含小数部分。即使在除法操作中可能会出现小数部分,取整操作也会将其向上舍入到最接近的整数。
//强制转换为 long 确保结果是一个整数数据类型,以便在后续的计算和逻辑中使用。
//将sourceFile.length()乘以1.0然后再除以chunkSize的目的是将除法操作的结果转换为浮点数(double),而不是整数(int)。这样做的原因是为了确保精确的浮点数除法,以避免在除法操作中截断小数部分。
long chunkNum=(long)Math.ceil(sourceFile.length()*1.0/chunkSize);
System.out.println("分块总数:"+chunkNum);
// 建立字节数组,用于缓存从源文件读取的数据:缓冲区大小1kb
byte[] b=new byte[1024];
// 使用RandomAccessFile来实现快速随机访问文件,以只读方式打开源文件
/**
* - 构造方法:RandomAccessFile(String name, String mode),用于创建RandomAccessFile对象,其中name为文件名,mode为文件打开模式("r"表示只读,"rw"表示读写)。
* - seek(long pos)方法:用于将文件指针移动到指定位置。
* - read()方法:用于读取一个字节。
* - read(byte[] b)方法:用于读取一定数量的字节到一个字节数组中。
* - write(int b)方法:用于写入一个字节。
* - write(byte[] b)方法:用于写入一个字节数组。
* */
RandomAccessFile raf_read=new RandomAccessFile(sourceFile,"r");
// 循环处理每个分块:使用for循环将待分块的文件分成多个小文件。
for(int i=0;i<chunkNum;i++){
// 根据序号创建新的块文件:首先创建一个File对象,
// 补充:Java中有自动类型转换的机制。在这里,Java会将int类型的i自动转换为String类型,所以chunkPath+i是它是 chunkPath 和 i 的拼接结果。不会出现报错
File file=new File(chunkPath+i);
if (file.exists()){
// 如果块文件已经存在,先删除。然后在本地磁盘上创建该目录
file.delete();
}
// 创建新的块文件:创建这个分块文件(理解为只有文件名的空文件)
boolean newFile=file.createNewFile();
// 如果成功创建新文件,则开始向其中写入数据
if (newFile){
// 创建一个RandomAccessFile对象raf_write,用于写入分块后的文件。
RandomAccessFile raf_write=new RandomAccessFile(file,"rw");
int len=-1;
// 使用while循环读取待分块的文件
while ((len=raf_read.read(b))!=-1){
// 将读取到的数据写入分块后的文件中
raf_write.write(b,0,len);
// 直到该文件的大小达到chunkSize即1M
if (file.length()>=chunkSize){
break;
}
}
raf_write.close();
System.out.println("完成分块"+i);
}
}
raf_read.close();
}
测试结果: