Java IO流实例 --- 文件切割合并配置

1 文件切割

切割方式:

1 按大小切,文件有多大,每份切多少,都是事先规定好的
2 按重量切,不管文件有多大,就切 N份 — 这种方式比较好

有几个文件,就需要几个输出流。一个文件,关联一个流
用读取流 关联源文件

代码实现

FileInputStream fis = new FileInputStream(file);
/*
 定义一个1M的缓冲区
 如果定义的是 100M 缓冲区,那就 循环往里写,循环写100次
*/
byte[] buf = new byte[SIZE]; 
FileOutputStream fos = null; // 创建目的
int len = 0;
int count = 1;
File dir = new File("c:\\partfiles"); // 定义切割的文件存放的位置
if(!dir.exists())
   dir.mkdirs();
while( (len=fis.read(buf)) != -1 )  {
 // --- 注释
 fos = new FileOutputStream(new File(dir,(count++)+".part") ); 
 fos.write(buf,0,len);
}
fos.close();
fis.close();

注:
// — 注释 下面 写
fos = new FileOutputStream("1.txt"); 不行
因为我们产生的是 碎片文件,有好多个,不能只写一个文件
文件要有编号,所以,对文件名,要进行处理
扩展名是 txt 也不靠谱,因为切的文件可能是 mp3 mp4 jpg等
专业的碎片 起名 part 1.part

2 文件合并
//将 碎片文件和流对象 关联   并存储到集合中
ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
for(int x=0; x<partFiles.length; x++){
    al.add(new FileInputStream( new File(dir,x+".part")));
}
//将多个流合并成一个序列流
Enumeration<FileInputStream> en = Collections.enumeration(al);
SequenceInputStream sis = new SequenceInputStream(en);

FileOutputStream fos = new FileOutputStream(new File(dir,filename));
byte[] buf = new byte[1024];

int len =0;
while( (len=sis.read(buf)) !=-1 ) {
    fos.write(buf,0,len);
}

fos.close();
sis.close();
3 改进

上面的写法,有两处不足:

1 切割时,不知道被切割文件的个数
2 合并前,不知道原来文件的类型 — 2 的写法是按照 默认知道来做的

思路:碎片记录的是,主体文件的内容,再弄一文件,记录碎片的信息

文件切割:

带着配置信息的切割

1 切割文件时,必须记录住被切割文件的名称,以及切割出来碎片文件的个数。 以方便于合并
这个信息为了进行描述,使用键值对的方式。用到了properties对象
Properties prop = new Properties();
2 将被切割文件的信息保存到prop集合中
prop.setProperty("partcount", count+""); // 碎片文件的个数
prop.setProperty("filename", file.getName());
3 如果有N个碎片,properties命名为 N+1.properties
fos = new FileOutputStream(new File(dir,count+".properties"));
4 将prop集合中的数据存储到文件中
prop.store(fos, "save file info");

知识储备
基础知识非常重要,再复杂的功能也是由一个个基础的方法组成的,熟练,深刻的理解,掌握基础知识!!!

1 关于File 的构造函数的理解
File(File parent,String Child)
File(String parent,String child)
根据给定 parent路径名 和 child路径名 创建一个新的 File实例
2 关于 count++ 的理解
命名切割的文件是 1 2 3 4 ,为什么 count =5
很简单 i++; 先使用,再加1
int x=1;
int y= x++;;
for(int i=0;i<4;i++){
System.out.println(“y=”+y);
System.out.println(“x=”+x);
}

输出结果 y= 1,2,3,4 x= 2,3,4,5
因为 y=x++; 是先使用再加 1 ,x 直接输出 x++, 加1后的结果

代码

public class SplitFileDemo {
	
	// 定义一个 3M大小的 缓冲区  写 3145728比较好,写 1024*1024*3,
	// 程序在运行的时候,还要先运算一遍,影响效率
	private static final int SIZE = 3145728;
	
	public static void main(String[] args) throws IOException {
		
		File file = new File("E:\\tm.mp3");
		splitFile(file);

	}

	private static void splitFile(File file) throws IOException {
		
		// 用读取流 关联源文件
		FileInputStream fis = new FileInputStream(file);
		// 定义一个 3M的缓冲区
		byte[] buf = new byte[SIZE];
		
		// 创建目的
		FileOutputStream fos = null;
		int len = 0;
		int count = 1;
		
		/*
		 *  切割文件时,必须记住被切割的文件的名称,以及切割出来的碎片文件的个数
		 *  以方便合并。
		 *  这个信息为了进行描述,使用键值对的方式,用到了 properties对象
		 */
		
		Properties prop = new Properties();
		
		File dir = new File("E:\\partFiles"); // 定义切割文件存放的位置
		if(!dir.exists()){
			dir.mkdirs();
		}
		
		while((len=fis.read(buf))!=-1){
			
			fos = new FileOutputStream(new File(dir,(count++)+".part"));
			fos.write(buf,0,len);
			fos.close();
		}
		
		// 将被切割文件的信息 保存到 prop集合中
		/*
		 *  setProperty(String value,String key)
		 *  调用 Hashtable的方法 put
		 */
		prop.setProperty("partcount",count+"");
		prop.setProperty("filename",file.getName());
		
		// 如果有N个碎片,properties命名为 N+1.properties
		fos = new FileOutputStream(new File(dir,count+".properties"));
		
		// 将 prop集合中的数据 存储到文件中
		prop.store(fos,"save file info");
		
		fos.close();
		fis.close();
	}
}

文件合并

1 先拿到该目录下的 配置文件对象

配置信息拿不到,或者文件不存在,就不用合并了
配置文件怎么拿

我们不知道配置文件的信息,但是知道配置文件的扩展名是 .properties
所以要准备一个过滤器
File[] files = dir.listFiles(new SuffixFilter(".properties")); // 获取指定目录下的配置文件对象

2 记录配置文件对象

File confile = files[0];

3 获取该文件中的信息

Properties prop = new Properties();
FileInputStream fis = new FileInputStream(confile);
prop.load(fis);
String filename = prop.getProperty(“filename”);
int count = Integer.parseInt(prop.getProperty(“partcount”));

4 获取该目录下的所有碎片文件

File[] partFiles = dir.listFiles(new SuffixFilter(".part"));

5 将碎片文件和流对象关联 并存储到集合中

ArrayList al = new ArrayList();
for(int x=0; x<partFiles.length; x++){
al.add(new FileInputStream(partFiles[x]));
}

6 将多个流合并成一个序列流

过滤器

public class SuffixFilter implements FilenameFilter{
	
	private String suffix;
	
	public SuffixFilter(String suffix){
		super();
		this.suffix = suffix;
	}

	public boolean accept(File dir, String name) {
		
		return name.endsWith(suffix);
	}

}

合并代码

public class MergeFileDemo {

	/**
	 *    文件合并
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		
		File dir = new File("E:\\partFiles"); // 先关联 要合并的文件
		mergeFile(dir);
	}

	private static void mergeFile(File dir) throws IOException {
		
		// 合并文件,给的是文件夹,里面有一堆文件/目录
		// 获取指定目录下的 配置文件对象
		File[] files = dir.listFiles(new SuffixFilter(".properties"));
		
		if(files.length !=1){
			throw new RuntimeException(dir+",该目录下没有properties扩展名的文件或者不唯一");
		}
		// 记录配置文件对象
		File confile = files[0];
		
		// 获取该文件中的信息
		Properties prop = new Properties();
		FileInputStream fis = new FileInputStream(confile);
		prop.load(fis);
		
		String filename = prop.getProperty("filename");
		int count = Integer.parseInt(prop.getProperty("partcount"));
		
		// 获取该目录下的所有碎片文件
		File[] partFiles = dir.listFiles(new SuffixFilter(".part"));
		if(partFiles.length !=(count-1)){
			throw new RuntimeException(" 碎片文件不符合要求,个数不对!应该"+count+"个");
		}
		
		// 将碎片文件 和 流对象 关联,并存储到集合中
		ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
		for(int x=0;x<partFiles.length;x++){
			al.add(new FileInputStream(partFiles[x]));
		}
		
		// 将多个流 合并成一个流
		Enumeration<FileInputStream> en = Collections.enumeration(al);
		SequenceInputStream sis = new SequenceInputStream(en);
		FileOutputStream fos = new FileOutputStream(new File(dir,filename));
		
		byte[] buf = new byte[1024];
		int len = 0;
		while((len=sis.read(buf))!=-1){
			fos.write(buf,0,len);
		}
		
		fos.close();
		sis.close();
	}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值