21,序列流SequenceInputStream
21.1序列流的作用
序列流也是字节流InputStream的子类,序列流可以完成对多个字节流的合并。
其构造函数可以接收两个字节流对象,或一个包含字节流的枚举对象。
SequenceInputStream
(Enumeration<? extends InputStream> e)
SequenceInputStream
(InputStream s1, InputStream s2)
如图:
序列流可以通过一个包含多个流的枚举对象,获取多个流中的关联的源数据,通过序过流读取各个流关联的数据并通过输出流完成对多个源数据的合并。
如何才能获取一个包含多个流的枚举对象:
这里需要用到集合,Vector集合的elements()方法,就能拿到一个集合的枚举对象,但是考虑到Vector集合很少使用,所以这里考虑使用,Collections类中的enumeration(Collection<T>c);方法,将一个集合作为参数传给这个方法,进面获取到这个集合的枚举对象。
演示流的合并:
import java.io.FileInputStream;
importjava.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
public class SequenceInputStreamDemo {
public static void main(String[] args)throws IOException {
demo();
}
public static void demo()throws IOException {
//1,创建ArrayList集合
ArrayList<InputStream> al=new ArrayList<InputStream>();
//2,往集合中添加字节流对象,并关联源。
al.add(new FileInputStream("d:\\1.txt"));
al.add(new FileInputStream("d:\\2.txt"));
al.add(new FileInputStream("d:\\3.txt"));
al.add(new FileInputStream("d:\\4.txt"));
//3,通过Collections的enumeration()方法,获取集合的枚举对象。
Enumeration<InputStream> en=Collections.enumeration(al);
//4,创建序列流对象,接收集合的枚举对象,完成对流的合并。
SequenceInputStream sis=new SequenceInputStream(en);
//5,创建一个字节输出流对象,用于将多个流关联的源数据,进行合并。
FileOutputStream fis=new FileOutputStream("d:\\5.txt");
//6,创建一个字节数组作为临时存储容器。
byte[]buf=newbyte[1024];
int len=0;
while((len=sis.read(buf))!=-1){//循环读取
fis.write(buf,0,len);//写入目的地
}
fis.close();//关闭资源。
sis.close();//关闭资源。
}
}
序列流通过枚举对象,对多个流进行合并为一个流,并把合个流关联的源合并为一个源,通过序列流完成读取源数据的工作,再通过输出流对数据进行合并。使用此流就可以完成碎片文件的合并,如:文件被切割后的合并。
如:文件切割+合并+配置文件
文件的切割+配置文件
思路:
1,要完成文件切割,就要有操作文件的流,这里可以使用字节流。
2,文件切割,就要有切割的大小,可以定义一个字节数组,将数据读入数组中,存满后就写入目的地,并命名,每次命名不同,就能生成很多的碎片文件。
3,配置文件的生成可以使用Properties集合,配置文件中存放源文件名,和碎片文件个数。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
public class SplitFileDemo {
public static void main(String[] args) {
String filepath="d:\\b.jpg";
splitFile(filepath);
}
public static void splitFile(String filepath) {
//将文件名封装在File对象中。
File file=new File(filepath);
//创建一个File对象,将目标目录进行封装。
File dstdir=new File("d:\\split");
if(!dstdir.exists()){
dstdir.mkdir();
}
//创建流对象并关联源文件。
FileInputStream fis=null;
FileOutputStream fos=null;//每个碎片文件,都需要一个流输出,所以先进行流的声明。
int count=0;//用来记录碎片文件的个数。
byte[]buf=newbyte[1024*1024];//定义一个字节数组,用于文件切割的大小。
int len=0;
try{
fis=new FileInputStream(file);
while((len=fis.read(buf))!=-1){
fos=new FileOutputStream(new File(dstdir,(count++)+".part"));
fos.write(buf,0,len);
}
//创建一个Properties集合,用于存放配置文件信息。
Properties prop=new Properties();
//创建一个流对象,用于产生配置文件。
fos=new FileOutputStream(new File(dstdir,count+".properites"));
//设置配置文件中的信息
prop.setProperty("filename", file.getName());
prop.setProperty("count", count+"");
prop.setProperty();
//将配置文件通过流保存在硬盘中。
prop.store(fos, "");
}catch(IOException e){
}finally{
//关闭资源
if(fos!=null)
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
if(fis!=null)
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
文件合并+配置文件
通过读取配置文件,完成对碎片文件的合并。
首先,需要读取配置文件信息,获取碎片文件个数等信息,可以使用文件名过滤器,过滤碎片文件,注意不能把配置文件也添加到了集合中。通过流来关联碎片文件,添加到集合中,再获取枚举对象,最后通过序列流完成合并。
import java.io.File;
import java.io.FileInputStream;
importjava.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Properties;
public class MergerFileDemo {
public staticvoid main(String[] args) {
String dstdir="d:\\split";
megerFile(dstdir);
}
public static void megerFile(String dstdir) {
//声明流对象
FileInputStream fis=null;
FileOutputStream fos=null;
SequenceInputStream sis=null;
try {
//将目标目录封装在File对象中。
File dir=new File(dstdir);
//创建一个过滤器,过滤.part文件。
FilenameFilter filter=new FilenameFilter(){
@Override
publicboolean accept(File dir, String name) {
return name.endsWith(".part");
}};
//创建一个集合,用于存储字节流对象。
ArrayList<InputStream> al=new ArrayList<InputStream>();
//创建一个Properties集合。
Properties prop=new Properties();
File []file=dir.listFiles();
for(File files:file){
if(filter.accept(files, files.getName())){
al.add(new FileInputStream(files));
}else{
fis=new FileInputStream(files);
//通过流将配置加载进集合
prop.load(fis);
break;
}
}
//通过配置文件的键获取值。
String filename=prop.getProperty("filename");
//获取集合的枚举对象。
Enumeration<InputStream> en=Collections.enumeration(al);
//实例化序列流
sis=new SequenceInputStream(en);
//实列化字节输出流,目标文件名为配置文件中的文件件名。目录为碎片文件的所在目录。
fos=new FileOutputStream(new File(dir,filename));
int len=0;
byte[]buf=newbyte[1024];
//读取操作。
while((len=sis.read(buf))!=-1){
//写入输出流。
fos.write(buf,0,len);
}
} catch (IOException e) {
e.printStackTrace();
//以下关闭资源
}finally{
if(fos!=null)
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
if(sis!=null)
try {
sis.close();
} catch (IOException e) {
e.printStackTrace();
}
if(fis!=null)
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
总结:序列流是通过集合的枚举对象,完成流所关联源的合并,所以序列流和枚举对象关系紧密。枚举对象,可以通过Collections类的enumeration(Collection<T> coll);方法获取。拿到存储字节流元素的集合枚举对象,就能够完成序列流的实例化。
---------------------- ASP.Net+Android+IOS开发、 .Net培训、期待与您交流! ----------------------