实现IO流拆分合并的集合功能(多个文本文件进行合并/一个视频文件切割成单个文件/多个视频流合并成单个视频文件/前后端视频文件的断点续传功能)
package com.example.yygoods.controller;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.util.*;
import java.io.*;
@RestController
public class SequenceStream {
Vector<InputStream> vectorStreams = new Vector<>();
/*
* 实现多个文本文件进行合并
* Vector作用和数组类似,存储数据,功能会比数组强大,如: 可以返回枚举类型数据
* 注释:SequenceInputStream参数必须是枚举类型的数据
* vectorStreams.elements()返回此向量的组件的枚举
**/
@GetMapping("/streamMerge")
public String streamMerge () {
try {
String UPLOAD_DIR = System.getProperty("user.dir");
InputStream inputStream_a = new FileInputStream(UPLOAD_DIR + "\\1.txt");
InputStream inputStream_b = new FileInputStream(UPLOAD_DIR + "\\2.txt");
vectorStreams.add(inputStream_a);
vectorStreams.add(inputStream_b);
SequenceInputStream sis = new SequenceInputStream(vectorStreams.elements());
OutputStream outputStream = new FileOutputStream(UPLOAD_DIR + "\\merge.txt");
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = sis.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.close();
sis.close();
} catch (Exception e) {
return "Error merging files: " + e.getMessage();
}
return "index";
}
/*
* 实现一个视频文件切割成单个文件
* RandomAccessFile可以在任意地方进行读写文件
* getFilePointer():返回文件记录指针的当前位置
* seek(long pos):将文件记录指针定位到pos位置
**/
@GetMapping("/splitVideo")
public String splitVideo () {
try {
String UPLOAD_DIR = System.getProperty("user.dir");
File source_file = new File(UPLOAD_DIR + "\\file.mp4");
File chunk_file = new File(UPLOAD_DIR + "\\chunk");
if(!chunk_file.exists()){
chunk_file.mkdirs();
}
//切片大小设置为100kb
long chunkSize = 102400;
//分块数量
long chunkNum = (long) Math.ceil(source_file.length() * 1.0 / chunkSize);
System.out.println("分块总数:"+chunkNum);
//缓冲区大小
byte[] b = new byte[1024];
//使用RandomAccessFile访问文件
RandomAccessFile source_file_rf = new RandomAccessFile(source_file, "r");
for (int i = 0; i < chunkNum; i++) {
//创建分块文件,如果存在删除,在创建新建文件
File file = new File(UPLOAD_DIR + "\\chunk\\" + i);
if(file.exists()){
file.delete();
}
boolean newFile = file.createNewFile();
// 创建成功,读取原文件把流写入到新建的新建文件中
if (newFile) {
RandomAccessFile chunk_file_rf = new RandomAccessFile(file, "rw");
int len = -1;
while ((len = source_file_rf.read(b)) != -1) {
chunk_file_rf.write(b, 0, len);
if (file.length() >= chunkSize) {
break;
}
}
chunk_file_rf.close();
}
}
source_file_rf.close();
} catch (Exception e) {
return "Error merging files: " + e.getMessage();
}
return "index";
}
/*
* 实现多个视频流合并成单个视频文件
**/
@GetMapping("/mergVideo")
public String mergVideo () {
try {
String UPLOAD_DIR = System.getProperty("user.dir");
File origin_file = new File(UPLOAD_DIR + "\\file.mp4");
File merge_file = new File(UPLOAD_DIR + "\\merge_file.mp4");
File chunk_file = new File(UPLOAD_DIR + "\\chunk");
if(merge_file.exists()) {
merge_file.delete();
}
//创建新的合并文件
merge_file.createNewFile();
//使用RandomAccessFile读写文件
RandomAccessFile raf_write = new RandomAccessFile(merge_file, "rw");
//指针指向文件顶端
raf_write.seek(0);
//缓冲区
byte[] b = new byte[1024];
//分块列表
File[] fileArray = chunk_file.listFiles();
// 转成集合,便于排序
List<File> fileList = Arrays.asList(fileArray);
System.out.println("集合文件:" + fileList);
// 从小到大排序
Collections.sort(fileList, new Comparator<File>() {
@Override
public int compare(File o1, File o2) {
return Integer.parseInt(o1.getName()) - Integer.parseInt(o2.getName());
}
});
System.out.println("排序的集合文件:" + fileList);
// 遍历集合文件,读取每个文件的内容再写入到新文件中
for (File chunkFile : fileList) {
RandomAccessFile raf_read = new RandomAccessFile(chunkFile, "rw");
int len = -1;
while ((len = raf_read.read(b)) != -1) {
raf_write.write(b, 0, len);
}
raf_read.close();
}
raf_write.close();
//校验文件
FileInputStream fileInputStream = new FileInputStream(origin_file);
FileInputStream mergeFileStream = new FileInputStream(merge_file);
//取出原始文件的md5
String originalMd5 = DigestUtils.md5Hex(fileInputStream);
//取出合并文件的md5进行比较
String mergeFileMd5 = DigestUtils.md5Hex(mergeFileStream);
if (originalMd5.equals(mergeFileMd5)) {
System.out.println("合并文件成功");
} else {
System.out.println("合并文件失败");
}
} catch (Exception e) {
return "Error merging files: " + e.getMessage();
}
return "index";
}
/*
* 实现前后端视频文件的断点续传功能
* Vector作用和数组类似,存储数据,功能会比数组强大,如: 可以返回枚举类型数据
* 注释:SequenceInputStream参数必须是枚举类型的数据
* vectorStreams.elements()返回此向量的组件的枚举
**/
@PostMapping("/merge-files")
public String mergeFiles(@RequestParam MultipartFile file, @RequestParam Integer index, @RequestParam Integer total, @RequestParam String name) {
try {
InputStream inputStream = file.getInputStream();
vectorStreams.add(inputStream);
if (index < total) {
return "success" + index;
} else {
SequenceInputStream sis = new SequenceInputStream(vectorStreams.elements());
// 假设你想把合并后的流保存为一个新文件
String UPLOAD_DIR = System.getProperty("user.dir");
File outfile = new File(UPLOAD_DIR + "\\" + name);
FileOutputStream fos = new FileOutputStream(outfile);
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = sis.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
sis.close();
fos.close();
vectorStreams.clear();
return "success";
}
} catch (Exception e) {
return "Error merging files: " + e.getMessage();
}
}
}