将一个53k的图片以10k为单位进行分割,最后再将分割的文件合并到一起。
首先进行文件的分割,这里使用了两种方法:
(1)其中splitFile(file)方法只是简单地将图片进行了分割。
(2)splitFile_2(file)方法除了将文件进行分割,还将一些配置信息进行了存储。 切割文件时,必须记录被切割文件的名称以及切割出来的文件的个数,以方便合并。这个信息为了进行很好地描述,使用键值对的方式进行存储,所以使用properties进行存储。
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.Properties;
public class Demo4 {
public static void main(String[] args) throws Exception {
//创建一个文件对象进行关联
File file=new File("d:\\16.jpg");
//splitFile(file);
splitFile_2(file);//以键值对的形式进行存储
}
private static void splitFile_2(File file) throws Exception {
//定义读入流,与文件相关联
FileInputStream fis=new FileInputStream(file);
//定义缓冲区10k 图片大小为53k
byte[] buf=new byte[1024*10];
int count=1;
//创建一个目的
FileOutputStream fos=null;//定义为null,因为不知道和谁关联
/*
* 切割文件时,必须记录被切割文件的名称以及切割出来的文件的个数,以方便合并
* 这个信息为了进行很好地描述,使用键值对的方式进行存储,所以使用properties进行存储
*/
Properties prop=new Properties();
File dir=new File("d:\\partfiles");
if(!dir.exists()){
dir.mkdirs();
}
int len=0;
while((len=fis.read(buf))!=-1){
fos=new FileOutputStream(new File(dir,(count++)+".part"));
fos.write(buf, 0, len);
}
//将被切割文件的信息保存到properties中
prop.setProperty("partcount", (--count)+"");//因为创建完文件后,Count进行了自增操作,所以真正分割得到的文件数应该再减去1
prop.setProperty("filename", file.getName());
//数据持久化
fos=new FileOutputStream(new File(dir,count+".properties"));
//将集合中的数据存储到文件中
prop.store(fos, "file infos");
fis.close();
fos.close();
}
private static void splitFile(File file) throws Exception {
//定义读入流,与文件相关联
FileInputStream fis=new FileInputStream(file);
//定义缓冲区10k 图片大小为53k
byte[] buf=new byte[1024*10];
//创建目的 1.part 2.part 3.part ...放到partfiles文件夹下
FileOutputStream fos=null;
File dir=new File("d:\\partfiles");
//不存在则创建
if(!dir.exists()){
dir.mkdir();
}
int len=0;
int count=1;//用于记录1.part 2.part 3.part文件名前面的编号
while((len=fis.read(buf))!=-1){
fos=new FileOutputStream(new File(dir,(count++)+".part"));
fos.write(buf, 0, len);
}
fos.close();
fis.close();
}
}
进行文件的合并
使用SquenceInputStream类可以实现字节输入流的合并。
由于要使用SquenceInputStream类,所以需要将输入流列表转换为Enumeration(枚举)类型。
Collections工具类中的enumeration方法,将集合转换为枚举类型。
//将分割的文件合并到一起
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Properties;
public class Demo5 {
public static void main(String[] args) throws Exception {
//将分割的文件进行合并
File dir=new File("d:\\partfiles");
mergeDir_2(dir);
}
private static void mergeDir_2(File dir) throws Exception {
//从properties文件中取出共分割了多少个文件
//通过过滤得到properties文件
File[] files=dir.listFiles(new SuffixFilter(".properties"));
if(files.length!=1){
throw new RuntimeException(dir+"该目录下没有properties扩展名的文件或者文件不唯一");
}
//记录配置文件对象
File config=files[0];//因为过滤出来只有一个对应的文件
//获取该文件中的信息
Properties prop=new Properties();
FileInputStream fis=new FileInputStream(config);
prop.load(fis);//通过load将文件中的信息放到集合中
String filename=prop.getProperty("filename");
int count=Integer.parseInt(prop.getProperty("partcount"));
//合并
mergeFile(dir,filename,count);
}
private static void mergeFile(File dir, String filename, int count) throws Exception {
ArrayList<FileInputStream> list=new ArrayList<>();
//将分割得到的文件放到集合中
for(int x=1;x<=count;x++){//一共循环分割文件的个数次
list.add(new FileInputStream(new File(dir,x+".part")));
}
Enumeration<FileInputStream> en=Collections.enumeration(list);//将集合转换为枚举类型
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();
}
}
class SuffixFilter implements FilenameFilter{
private String suffix;
public SuffixFilter(String suffix) {
this.suffix=suffix;
}
@Override
public boolean accept(File dir, String name) {
return name.endsWith(suffix);
}
}