Java文件的拆分与合并(二)

简介: package cn.com; import java.io.File; import java.io.FileInputStream; import java.
package cn.com;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.RandomAccessFile;
//文件的拆分和组合
//步骤:
//1 依据源文件大小和每块的大小计算出块数
//2 将每一块写到一个对应的文件
public class FileSeparatorAndUnite {
	long rawFileSize;
	long blocksNumber;
	String rawFileName=null;
	String [] allPaths=null;
	public static void main(String[] args) {
         FileSeparatorAndUnite test=new FileSeparatorAndUnite();
         //拆分文件
         String [] allPaths=test.separatorFile("F:\\2.jpg", 1024*10);
         //组合文件
         test.uniteFile(allPaths, "F:\\33.jpg");
	}
	
	/**
	 * @param rawFilePath   待拆分文件的路径
	 * @param perBlockSize  拆分后每份的大小
	 * @return              各部分路径的数组集合
	 */
	private String[] separatorFile(String rawFilePath,long perBlockSize){
		File rawFile=new File(rawFilePath);
		rawFileName=rawFile.getName();
		rawFileSize=rawFile.length();
		blocksNumber=getBlocksNumber(rawFileSize,perBlockSize);
		allPaths=new String[(int)blocksNumber];
		if (blocksNumber==1) {
			perBlockSize=rawFileSize;
		}
		long perPartSize=0;
		long perPartBeginPosition=0;
		String perPartPath=null;
		for (int i = 1; i <=blocksNumber; i++) {
			if (i<blocksNumber) {
				//每一块的大小就为perBlockSize
				perPartSize=perBlockSize;
			} else {
				//最后一块的大小为总大小-该块的起始位置
                perPartSize=rawFileSize-perPartBeginPosition;
			}
			//得到每一块的path
			if (blocksNumber==1) {
				perPartPath=rawFilePath+".bat";
			} else {
				perPartPath=getPerPartFilePath(rawFilePath, i);
			}
			//操作每一块
			//第一次调用时perPartBeginPosition当然为0
			writePerPartToFile(rawFilePath, perPartPath, perBlockSize, perPartBeginPosition); 
			//计算每一块的在原文件中的起始位置.
			perPartBeginPosition=perPartBeginPosition+perPartSize;
			//保存每一块的路径
			allPaths[i-1]=perPartPath;
		}
		return allPaths;
		
	}
	
	/**
	 * @param rawFilePath       原文件路径
	 * @param perPartFilePath   每部分对应的路径
	 * @param blockSize         每部分的块大小
	 * @param beginPosition     每部分在原文件中的开始位置 
	 * @return
	 * 在这里  len=len-(int)(writedBytes-blockSize)有些不好理解
	 * 假设blockSize=2100,每次写入1024,那么两次后还剩余
	 * 2100-1024*2=52
	 * 如果再写入1024,那么就会报错,超出了最大范围.
	 * 所以还能写入的=blockSize-已经写入的大小(writedBytes)
	 * 因为在if语句前面已经有了赋值语句writedBytes=writedBytes+len;
	 * 所以需要:len=len-(int)(writedBytes-blockSize)
	 * 其实代入:len=len-(int)(writedBytes+len-blockSize)
	 * 可以得知:len=blockSize-writedBytes
	 */
	public boolean writePerPartToFile(String rawFilePath,String perPartFilePath,long blockSize,long beginPosition){
		RandomAccessFile raf=null;
		FileOutputStream fos=null;
		byte [] buffer=new byte[8*1024];
		int len=0;
		long writedBytes=0;
		try {
			raf=new RandomAccessFile(rawFilePath, "r");
			raf.seek(beginPosition);
			fos=new FileOutputStream(perPartFilePath);
			while ((len=raf.read(buffer))!=-1) {
				if (writedBytes<blockSize) {
					writedBytes=writedBytes+len;
					if (writedBytes<=blockSize) {
						fos.write(buffer, 0, len);
					} 
					else {
                        len=len-(int)(writedBytes-blockSize);
                        fos.write(buffer, 0, len);
					}
				} 
				
			}
		} catch (Exception e) {
			try {
				if (fos!=null) {
					fos.close();
				}
				if (raf!=null) {
					raf.close();
				}
			} catch (Exception ex) {
			}
			return false;
		}
		return true;
	}
	
	/**
	 * @param rawFileSize   原文件大小
	 * @param perBlockSize  每块的大小
	 * @return              拆分后块数
	 */
	public long getBlocksNumber(long rawFileSize,long perBlockSize){
		if (rawFileSize<=perBlockSize) {
			return 1;
		} else {
            if (rawFileSize%perBlockSize==0) {
				return ((rawFileSize/perBlockSize)+1);
			} else {
                return rawFileSize/perBlockSize;
			}
		}
	}
	
	/**
	 * @param rawFilePath   原文件路径
	 * @param blockNumer    当前块号码
	 * @return              当前块对应的路径
	 */
	public String getPerPartFilePath(String rawFilePath,int blockNumer){
		String perPartFilePath=rawFilePath+".part"+blockNumer;
		return perPartFilePath;
	}
	
	/**
	 * @param partsPaths      各部分路径
	 * @param unitedFilePath  合并后文件路径
	 */
	public void uniteFile(String [] partsPaths,String unitedFilePath){
		try {
			File perPartFile=null;
			File unitedFile=new File(unitedFilePath);
			FileOutputStream fos=new FileOutputStream(unitedFile);
			FileInputStream fis=null;
			for (int i = 0; i < partsPaths.length; i++) {
				perPartFile=new File(partsPaths[i]);
				fis=new FileInputStream(perPartFile);
				byte [] buffer=new byte[1024*8];
				int len=0;
				while ((len=fis.read(buffer))!=-1) {
					fos.write(buffer, 0, len);
				}
			}
			fis.close();
			fos.close();
		} catch (Exception e) {
		}
	}
}

相关文章
|
16天前
|
Arthas Java 测试技术
Java字节码文件、组成,jclasslib插件、阿里arthas工具,Java注解
Java字节码文件、组成、详解、分析;常用工具,jclasslib插件、阿里arthas工具;如何定位线上问题;Java注解
Java字节码文件、组成,jclasslib插件、阿里arthas工具,Java注解
|
21小时前
|
Java 大数据 API
Java 流(Stream)、文件(File)和IO的区别
Java中的流(Stream)、文件(File)和输入/输出(I/O)是处理数据的关键概念。`File`类用于基本文件操作,如创建、删除和检查文件;流则提供了数据读写的抽象机制,适用于文件、内存和网络等多种数据源;I/O涵盖更广泛的输入输出操作,包括文件I/O、网络通信等,并支持异常处理和缓冲等功能。实际开发中,这三者常结合使用,以实现高效的数据处理。例如,`File`用于管理文件路径,`Stream`用于读写数据,I/O则处理复杂的输入输出需求。
|
15天前
|
Java API 开发者
【Java字节码操控新篇章】JDK 22类文件API预览:解锁Java底层的无限可能!
【9月更文挑战第6天】JDK 22的类文件API为Java开发者们打开了一扇通往Java底层世界的大门。通过这个API,我们可以更加深入地理解Java程序的工作原理,实现更加灵活和强大的功能。虽然目前它还处于预览版阶段,但我们已经可以预见其在未来Java开发中的重要地位。让我们共同期待Java字节码操控新篇章的到来!
|
13天前
|
Java API 开发者
【Java字节码的掌控者】JDK 22类文件API:解锁Java深层次的奥秘,赋能开发者无限可能!
【9月更文挑战第8天】JDK 22类文件API的引入,为Java开发者们打开了一扇通往Java字节码操控新世界的大门。通过这个API,我们可以更加深入地理解Java程序的底层行为,实现更加高效、可靠和创新的Java应用。虽然目前它还处于预览版阶段,但我们已经可以预见其在未来Java开发中的重要地位。让我们共同期待Java字节码操控新篇章的到来,并积极探索类文件API带来的无限可能!
|
14天前
|
算法 Java
Java 压缩文件
在Java中压缩文件是一个常见的需求,通常可以通过使用Java自带的`java.util.zip`包来实现。这个包提供了`ZipOutputStream`类来创建ZIP格式的压缩文件。以下是一个简单的示例,展示了如何将多个文件压缩到一个ZIP文件中。 ### 示例:将多个文件压缩到一个ZIP文件中 ```java import java.io.*; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class ZipFilesExample { public static vo
|
26天前
|
Java 应用服务中间件 HSF
Java应用结构规范问题之配置Logback以仅记录错误级别的日志到一个滚动文件中的问题如何解决
Java应用结构规范问题之配置Logback以仅记录错误级别的日志到一个滚动文件中的问题如何解决
|
21天前
|
Java
java判断文件内容不为空
请注意,在实际的生产环境中,处理文件时需要考虑异常处理。在上述代码中,如果在文件读取过程中发生 `IOException`,则会被捕获,并在控制台打印堆栈跟踪信息。在更复杂的系统中,可能还需要更精细的异常处理策略。
30 0
|
7天前
|
存储 缓存 安全
【Java面试题汇总】多线程、JUC、锁篇(2023版)
线程和进程的区别、CAS的ABA问题、AQS、哪些地方使用了CAS、怎么保证线程安全、线程同步方式、synchronized的用法及原理、Lock、volatile、线程的六个状态、ThreadLocal、线程通信方式、创建方式、两种创建线程池的方法、线程池设置合适的线程数、线程安全的集合?ConcurrentHashMap、JUC
【Java面试题汇总】多线程、JUC、锁篇(2023版)
|
1天前
|
缓存 Java 应用服务中间件
Java虚拟线程探究与性能解析
本文主要介绍了阿里云在Java-虚拟-线程任务中的新进展和技术细节。
|
18天前
|
监控 Java 调度
【Java学习】多线程&JUC万字超详解
本文详细介绍了多线程的概念和三种实现方式,还有一些常见的成员方法,CPU的调动方式,多线程的生命周期,还有线程安全问题,锁和死锁的概念,以及等待唤醒机制,阻塞队列,多线程的六种状态,线程池等
79 6
【Java学习】多线程&JUC万字超详解