完整的文件切片和合并java实现代码

最近在学习大数据相关的知识点,其中需要实现文件的切片和合并,完整的java实现代码,以下贴出个人代码,仅供参考

首先建一个SplitUtil工具类,在工具类中有三个方法getSplitFile,getWrite,merge

1,文件拆分代码

public static void getSplitFile(String file,int count){
        
        //预分配文件所占用的磁盘空间,在磁盘创建一个指定大小的文件,“r”表示只读,“rw”支持随机读写
        try {
            RandomAccessFile raf = new RandomAccessFile(new File(file), "r");
            //计算文件大小
            long length = raf.length();
            System.out.println(length);
            //计算文件切片后每一份文件的大小
            long maxSize = length / count;
            
            System.out.println(maxSize);
            
            long offset = 0L;//定义初始文件的偏移量(读取进度)
            //开始切割文件
            for(int i = 0; i < count - 1; i++){ //count-1最后一份文件不处理
                //标记初始化
                long fbegin = offset;
                //分割第几份文件
                long fend = (i+1) * maxSize;
                //写入文件
                offset = getWrite(file, i, fbegin, fend);
                
            }
            
            //剩余部分文件写入到最后一份(如果不能平平均分配的时候)
            if (length - offset > 0) {
                //写入文件
                getWrite(file, count-1, offset, length);
            }
            
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }

2,getWrite文件写入代码

 

/**
     * 指定文件每一份的边界,写入不同文件中
     * @param file 源文件
     * @param index 源文件的顺序标识
     * @param begin开始指针的位置
     * @param end 结束指针的位置
     * @return long
     */
    public static long getWrite(String file,int index,long begin,long end){
        
        long endPointer = 0L;
        try {
            //申明文件切割后的文件磁盘
            RandomAccessFile in = new RandomAccessFile(new File(file), "r");
            //定义一个可读,可写的文件并且后缀名为.tmp的二进制文件
            RandomAccessFile out = new RandomAccessFile(new File(file + "_" + index + ".tmp"), "rw");
            
            //申明具体每一文件的字节数组
            byte[] b = new byte[1024];
            int n = 0;
            //从指定位置读取文件字节流
            in.seek(begin);
            //判断文件流读取的边界
            while(in.getFilePointer() <= end && (n = in.read(b)) != -1){
                //从指定每一份文件的范围,写入不同的文件
                out.write(b, 0, n);
            }
            
            //定义当前读取文件的指针
            endPointer = in.getFilePointer();
            
            //关闭输入流
            in.close();
            //关闭输出流
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return endPointer;
    }

3.文件合并代码

/**
     * 文件合并
     * @param file 指定合并文件
     * @param tempFile 分割前的文件名
     * @param tempCount 文件个数
     */
    public static void merge(String file,String tempFile,int tempCount){
        RandomAccessFile raf = null;
        try {
            //申明随机读取文件RandomAccessFile
            raf = new RandomAccessFile(new File(file), "rw");
            //开始合并文件,对应切片的二进制文件
            for (int i = 0; i < tempCount; i++) {
                //读取切片文件
                RandomAccessFile reader = new RandomAccessFile(new File(tempFile + "_" + i + ".tmp"), "r");
                byte[] b = new byte[1024];
                int n = 0;
                while((n = reader.read(b)) != -1){
                    raf.write(b, 0, n);//一边读,一边写
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                raf.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

最后在主程序里面调用就可以了

public static void main(String[] args) {
        
        String file = "F:\\java-study\\img\\mv.jpg";
        int count = 5;
        
        //1.根据现有的文件编写文件编写文件切片工具类
        //2.写入到二进制临时文件
        //    getSplitFile(file, count);
        //3.根据实际的需求合并指定数量的文件
        String tempFile = "F:\\java-study\\img\\img.jpg";
        merge(file, tempFile, 5);
        
        
        
    }

以上代码可实现图片,文档,mp3,mp4等文件的拆分与合并,下面是图片切片和拆分的效果图

转载于:https://www.cnblogs.com/linlinyu/p/8665224.html

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前后端分离实现文件切片上传的流程通常如下: 前端: 1. 将大文件切分成多个小文件,每个小文件大小固定或者根据网络状况动态调整大小。 2. 对于每个小文件,使用 FormData 对象进行封装,并通过 AJAX 请求将其发送给后端。 3. 在发送请求时,需要同时传递当前切片的序号和总切片数,以便后端进行文件合并。 后端: 1. 接收前端传递的每个切片,并进行存储。 2. 每当接收到一个切片后,就检查是否已经接收到了所有切片,如果是,则进行文件合并操作。 3. 在合并文件时,可以使用 Java NIO 的 MappedByteBuffer 进行文件拼接,以提高效率。 下面是一个简单的 Java 代码实现: 前端: ```javascript // 切分文件 function sliceFile(file, chunkSize) { const chunks = [] let start = 0 let end = chunkSize while (start < file.size) { chunks.push(file.slice(start, end)) start = end end = start + chunkSize } return chunks } // 上传切片 function uploadChunk(url, formData, onProgress) { return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest() xhr.open('POST', url) xhr.upload.onprogress = onProgress xhr.onload = () => resolve(xhr.responseText) xhr.onerror = () => reject(xhr.statusText) xhr.send(formData) }) } const file = document.getElementById('file').files[0] const chunkSize = 1024 * 1024 // 1MB const chunks = sliceFile(file, chunkSize) const totalChunks = chunks.length let uploadedChunks = 0 for (let i = 0; i < totalChunks; i++) { const formData = new FormData() formData.append('chunk', chunks[i]) formData.append('filename', file.name) formData.append('chunkIndex', i) formData.append('totalChunks', totalChunks) uploadChunk('/upload', formData, e => { const progress = (uploadedChunks + e.loaded) / file.size * 100 console.log(`Upload progress: ${progress.toFixed(2)}%`) }).then(() => { uploadedChunks++ if (uploadedChunks === totalChunks) { console.log('Upload complete') } }) } ``` 后端: ```java @RestController public class UploadController { private final Map<String, MappedByteBuffer> bufferMap = new ConcurrentHashMap<>(); @PostMapping("/upload") public ResponseEntity<String> uploadChunk(@RequestParam("chunk") MultipartFile chunk, @RequestParam("filename") String filename, @RequestParam("chunkIndex") int chunkIndex, @RequestParam("totalChunks") int totalChunks) throws IOException { String key = filename + "-" + chunkIndex; File tempFile = new File(filename + ".temp"); try (RandomAccessFile raf = new RandomAccessFile(tempFile, "rw")) { raf.seek(chunkIndex * chunk.getSize()); raf.write(chunk.getBytes()); } if (chunkIndex == totalChunks - 1) { File outputFile = new File(filename); try (FileChannel outputChannel = new FileOutputStream(outputFile).getChannel()) { for (int i = 0; i < totalChunks; i++) { String bufferKey = filename + "-" + i; MappedByteBuffer buffer = bufferMap.get(bufferKey); if (buffer == null) { FileChannel inputChannel = new FileInputStream(tempFile).getChannel(); buffer = inputChannel.map(FileChannel.MapMode.READ_ONLY, i * chunk.getSize(), chunk.getSize()); bufferMap.put(bufferKey, buffer); inputChannel.close(); } outputChannel.write(buffer); } } tempFile.delete(); } return ResponseEntity.ok("Upload success"); } } ``` 这里使用了 ConcurrentHashMap 来存储每个切片的 MappedByteBuffer 对象,以避免重复读取文件。最后合并文件时,只需要将每个切片对应的 MappedByteBuffer 写入到目标文件中即可。注意,这里使用了 try-with-resources 语句来确保资源的正确关闭。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值