单线程实现

文件分割

在老的FAT32文件系统中,最大的单个文件大小必须保存在4G内,对于经常看电影的我这个是不能允许的。不过现在Windows有NTFS文件系统,Linux大部分发行版为Ext4文件系统,最大单个文件大小能大于4G。不过这二者并不能兼容。。格式化NTFS的U盘Linux不能识别,格式化Ext4的U盘Windows不能识别,只能用老的FAT32兼容二者。所以将文件分割,再进行拼接就很重要,文件经过分割了在网络上传输就十分方便,也能开多线程对每部分进行HASH提高处理效率。

最近看的BradPitt的《狂怒》

首先:对文件进行分割需要确定每一部分的大小,假设上面的 Fury.mkv 文件大小为 280M ,分割每一块设置默认大小为 64M ,所以:

对于最后一块,一般小于等于设定好的每块默认大小。 每块大小设置好了,接下来,就需要将文件的路径获取,代码中搭建输入流,将文件读入内存缓冲区中,再搭建输出流,将缓冲区输出到新的分割文件中。 再接下来实现就很简单了。 新建一个 FileSlice

类:有切割方法,拼接方法。

public class FileSlice {

/**

* 分割文件

* @param filePath 文件路径

* @param filePieceSize 文件每块大小,单位为字节,为-1则默认为每块64M

* @return 成功返回True,出错则返回False

*/

public static boolean slice(Path filePath, int filePieceSize){

return true;

}

/**

* 将分割好的文件重新链接

* @param filePath 被分割好的其中之一文件路径,默认其他块与其在同一目录下

* @param howManyParts 一共有多少块

* @return 成功返回True,出错则返回False

*/

public static boolean glue(Path filePath, int howManyParts){

return true;

}

}

接下来实现单线程的分割方法: 用图解的话应该是这样:

代码实现: 进入函数首先判断文件是否存在:

if (!Files.exists(filePath)){

return false;

}

接下来判断每块大小是否使用默认值:

if(filePieceSize == -1){

filePieceSize = 1024*1024*64;

}

将路径转换为文件对象,再计算将分割多少块:

File file = filePath.toFile();

int howManyParts = (int) Math.ceil(file.length() / (double)filePieceSize);

初始化输入输出流,出错输出错误信息,返回false,获得当前目录:

DataInputStream fileReader = null;

try {

fileReader = new DataInputStream(new FileInputStream(file));

} catch (FileNotFoundException e) {

e.printStackTrace();

System.out.println("文件找不到!");

return false;

}

DataOutputStream fileWriter;

Path dir = filePath.getParent();

接下来读取文件,并且分别输出到各个part文件中:

int readLength = -1;

long total = 0;

try {

for (int i = 1; i <= howManyParts ; i++){

//新建文件part i

Path temp = Files.createFile(dir.resolve(filePath.getFileName() + ".part" + i));

//搭建输出流

fileWriter = new DataOutputStream(new FileOutputStream(temp.toFile()));

//读取文件并输出

while ( (readLength = fileReader.read(buffer)) != -1){

fileWriter.write(buffer,0,readLength);

fileWriter.flush();

total += readLength;

if (total == filePieceSize){

total = 0;

break;

}

}

//part i的文件已经输出完毕,关闭流

fileWriter.close();

}

//读取完毕,关闭输入流

fileReader.close();

} catch (IOException e) {

e.printStackTrace();

System.out.println("IO错误!");

return false;

}

该函数已经实现完毕,接下来测试(由于电影Fury有14G。。太大了。。还是换个吧):

我是大哥大第5集,有729M,大概能分个12个part吧。

public static void main(String[] args) throws IOException {

double before = System.currentTimeMillis();

Path bigboss = Paths.get("D:\\Video\\我是大哥大\\我是大哥大.Kyou.kara.Ore.wa.Ep05.Chi_Jap.HDTVrip.1280X720.mp4");

FileSlice.slice(bigboss,-1);

double after = System.currentTimeMillis();

System.out.println("分割文件我是大哥大.Kyou.kara.Ore.wa.Ep05.Chi_Jap.HDTVrip.1280X720.mp4," + Files.size(bigboss) + "字节,总用时" + (after - before) + "ms" );

}

运行结果:

分割文件我是大哥大.Kyou.kara.Ore.wa.Ep05.Chi_Jap.HDTVrip.1280X720.mp4,765321889字节,总用时16335.0ms

速度还是挺慢的。。 下次还是换成多线程来实现,再来测试下速度。在单线程情况下一个普通的40分钟日剧都要15-30s左右,要是mkv格式的电影都要好久了。。不过其实极限应该不在CPU中执行的速度,而是在硬盘IO中,如果是普通硬盘那么就算是多线程也应该提速不了多少。。

文件拼接

这个就很简单了,和分割相反就OK。 直接上完整代码:

public static boolean glue(Path filePath, int howManyParts){

if (!Files.exists(filePath)){

return false;

}

//获取原始文件名

String filename = getOriginalFileName(filePath.getFileName().toString());

if (filename == null){

System.out.println("传入part文件名解析出错!");

return false;

}

//初始化缓冲区

byte [] buffer = new byte[1024 * 8];

//获取文件存储的路径

Path dir = filePath.getParent();

try {

DataInputStream fileReader = null;

//创建原始文件

Files.createFile(dir.resolve(filename));

//搭建原始文件输出流

DataOutputStream fileWriter = new DataOutputStream(new FileOutputStream(dir.resolve(filename).toFile()));

int readLength = -1;

for (int i = 1; i <= howManyParts ; i++){

//得到part i文件路径

Path temp = dir.resolve(filename + ".part" + i);

//搭建输入流

fileReader = new DataInputStream(new FileInputStream(temp.toFile()));

//读取文件并输出

while ( (readLength = fileReader.read(buffer)) != -1){

fileWriter.write(buffer,0,readLength);

fileWriter.flush();

}

//part i的文件已经读入完毕,关闭流

fileReader.close();

}

//写入完毕,关闭输出流

fileWriter.close();

} catch (IOException e) {

e.printStackTrace();

System.out.println("IO错误!");

return false;

}

return true;

}

再测试刚刚分割好的我是大哥大第5集

public static void main(String[] args) throws IOException {

double before = System.currentTimeMillis();

Path bigboss = Paths.get("D:\\Video\\我是大哥大\\我是大哥大.Kyou.kara.Ore.wa.Ep05.Chi_Jap.HDTVrip.1280X720.mp4.part1");

FileSlice.glue(bigboss,12);

double after = System.currentTimeMillis();

System.out.println("拼接12个part,用时" + (after - before) + "ms");

}

结果输出,用12s左右,还行。

拼接12个part,用时12147.0ms

打开播放毫无问题,最后截张图。

未完待续。。下次来使用多线程进行实现。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

java文件切割_Java实现文件切割拼接的实现代码相关推荐

  1. java 多种类型文件复制_java多种文件复制方式以及效率比较

    1.背景 java复制文件的方式其实有很多种,可以分为 传统的字节流读写复制FileInputStream,FileOutputStream,BufferedInputStream,BufferedO ...

  2. java io文件操作_java IO 文件操作方法总结

    java IO 文件操作方法总结 对于输入输出的理解: 输入输出,以程序为参考点,外部数据进入程序,通过输入流完成.程序将数据给外部设备,通过输出流完成. 文件Io的操作 //获取文件 File fi ...

  3. java class 结构_Java class文件的结构

    Java class文件的结构 class文件是Java源代码编译之后产生的二进制文件,代码中的各个项目严格按照Java的规范组织. class文件以一张表的形式组织代码中的各个部分: 名称 释义 大 ...

  4. java校验文件格式_Java 判断文件是否为文本格式,并获取文件编码格式,读取内容!...

    我们经常会遇到读取文件内容的情况,就需要判断文件是否为文本文件,及文件编码格式,防止无法读取内容或乱码出现情况. 根据文件扩展名判定不太准确,可能会遇到未知扩展名或被修改了扩展名,下面的测试类使用文件 ...

  5. java底层 文件操作_JAVA的文件操作【转】

    11.3 I/O类使用 由于在IO操作中,需要使用的数据源有很多,作为一个IO技术的初学者,从读写文件开始学习IO技术是一个比较好的选择.因为文件是一种常见的数据源,而且读写文件也是程序员进行IO编程 ...

  6. java读取空格_java 读取文件路径空格和中文的处理

    应用部署时,发生文件读取错误,发现是部署路径中含有空格的文件夹名,然后把应用服务器位置迁移了. 从网上找到如下方案: 1, TestURL().class.getResource("&quo ...

  7. java new file会创建文件吗_Java高级——文件与I/O流

    简介 本文分为四个部分,首先是介绍File类,概括了一下概念.构造方法及常用方法等,其次是描述了面对对象的三大特征,再次是对抽象类进行了简单的概述,最后从特性.使用等等几个方面对接口进行了一定的描述. ...

  8. java文件选择器_java中文件选择器JFileChooser的用法

    一般的说,大家用JFileChooser有两种用法:打开文件或文件夹.保存文件或文件夹.本文就打开和保存文件来介绍JFileChooser的用法. 头文件的声明: import javax.swing ...

  9. java 文件压缩_java实现文件压缩

    java实现文件压缩:主要是流与流之间的传递 代码如下: package com.cst.klocwork.service.zip; import java.io.File; import java. ...

最新文章

  1. 祝所有51cto的朋友光棍节快乐
  2. idea 快速定位到某一行的快捷键
  3. 微信小程序开发视频教程新鲜出炉
  4. hdu6438 Buy and Resell 买卖物品 ccpc网络赛 贪心
  5. php libmysqlclient,什么是php?以及mysqlnd与libmysqlclient
  6. 内部错误:无法加载 ABAP 报表 LVBRKF0I
  7. 为什么jsp写script代码报错_JSP 报错:ReferenceError: $ is not defined
  8. 通过base标签实现全网页新窗口链接。
  9. 在服务器端渲染完毕的 Angular Component,在客户端还会重新渲染一次吗?
  10. vue通过class获取dom_.NET Core通过Json或直接获取图形验证码(务必收藏备用)
  11. 2.数据结构笔记学习--线性表基本操作
  12. java堆和栈 常量池_GitHub - han-guang-xue/difference-of-stack-heap-pool: Java中堆、栈和常量池的区别...
  13. 微信AES-128-CBC加密解密
  14. 拓端tecdat|SAS用梯度提升回归树(GBDT)迁移学习预测抵押贷款拖欠风险和垃圾电子邮件数据
  15. CCV 调试 (一)
  16. ensp配置access口_eNSP初学者配置以太网2种链路端口:access、trunk
  17. CSND帐号居然又能用了,发个文章庆祝一下
  18. 创业之前你要先了解3大要点!!
  19. 51cto的火星语。
  20. 开源一款苹果 macOS 工具 - AppleParty(苹果派)

热门文章

  1. 百度产品经理笔试题目(长沙地区)
  2. oracle数据库报ora-01691错误--表空间容量溢出解决办法
  3. 2012年12月编程语言排行榜:年度语言非Objective-C莫属
  4. 微信小程序开发之——个人中心-介绍(1)
  5. 复旦情商课魅力女教师陈果上课语录(复制)
  6. 【VC++游戏开发#三】2D篇 —— 游戏之一:空中大战(SpaceWar)
  7. 如何开启浏览器硬件加速
  8. html 转换 pdf js插件,【jsPDF】jsPDF插件實現將html頁面轉換成PDF,並下載,支持分頁...
  9. 2021年全国大学生数据统计与分析竞赛-B题分析
  10. Linux下安装anaconda3