合并流 SequenceInputStream

SequenceInputStream主要用来将2个流合并在一起,比如将两个txt中的内容合并为另外一个txt。下面给出一个实例:

importjava.io.File;
importjava.io.FileInputStream;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.OutputStream;
importjava.io.SequenceInputStream;
/**
* 将两个文本文件合并为另外一个文本文件
* */
publicclassSequenceInputStreamDemo{
publicstaticvoidmain(String[] args) throwsIOException{
File file1 = newFile("d:"+ File.separator + "hello1.txt");
File file2 = newFile("d:"+ File.separator + "hello2.txt");
File file3 = newFile("d:"+ File.separator + "hello.txt");
InputStream input1 = newFileInputStream(file1);
InputStream input2 = newFileInputStream(file2);
OutputStream output = newFileOutputStream(file3);
// 合并流
SequenceInputStream sis = newSequenceInputStream(input1, input2);
inttemp = 0;
while((temp = sis.read()) != -1){
output.write(temp);
}
input1.close();
input2.close();
output.close();
sis.close();
}
}

【运行结果】

结果会在hello.txt文件中包含hello1.txt和hello2.txt文件中的内容。

文件压缩 ZipOutputStream类

先举一个压缩单个文件的例子吧:

importjava.io.File;
importjava.io.FileInputStream;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.InputStream;
importjava.util.zip.ZipEntry;
importjava.util.zip.ZipOutputStream;
publicclassZipOutputStreamDemo1{
publicstaticvoidmain(String[] args) throwsIOException{
File file = newFile("d:"+ File.separator + "hello.txt");
File zipFile = newFile("d:"+ File.separator + "hello.zip");
InputStream input = newFileInputStream(file);
ZipOutputStream zipOut = newZipOutputStream(newFileOutputStream(
zipFile));
zipOut.putNextEntry(newZipEntry(file.getName()));
// 设置注释
zipOut.setComment("hello");
inttemp = 0;
while((temp = input.read()) != -1){
zipOut.write(temp);
}
input.close();
zipOut.close();
}
}

【运行结果】

运行结果之前,我创建了一个hello.txt的文件,原本大小56个字节,但是压缩之后产生hello.zip之后,居然变成了175个字节,有点搞不懂。

不过结果肯定是正确的,我只是提出我的一个疑问而已。

上面的这个例子测试的是压缩单个文件,下面的们来看看如何压缩多个文件。

importjava.io.File;
importjava.io.FileInputStream;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.InputStream;
importjava.util.zip.ZipEntry;
importjava.util.zip.ZipOutputStream;
/**
* 一次性压缩多个文件
* */
publicclassZipOutputStreamDemo2{
publicstaticvoidmain(String[] args) throwsIOException{
// 要被压缩的文件夹
File file = newFile("d:"+ File.separator + "temp");
File zipFile = newFile("d:"+ File.separator + "zipFile.zip");
InputStream input = null;
ZipOutputStream zipOut = newZipOutputStream(newFileOutputStream(
zipFile));
zipOut.setComment("hello");
if(file.isDirectory()){
File[] files = file.listFiles();
for(inti = 0; i < files.length; ++i){
input = newFileInputStream(files[i]);
zipOut.putNextEntry(newZipEntry(file.getName()
+ File.separator + files[i].getName()));
inttemp = 0;
while((temp = input.read()) != -1){
zipOut.write(temp);
}
input.close();
}
}
zipOut.close();
}
}

【运行结果】

先看看要被压缩的文件吧:

接下来看看压缩之后的:

大家自然想到,既然能压缩,自然能解压缩,在谈解压缩之前,我们会用到一个ZipFile类,先给一个这个例子吧。java中的每一个压缩文件都是可以使用ZipFile来进行表示的

importjava.io.File;
importjava.io.IOException;
importjava.util.zip.ZipFile;
/**
* ZipFile演示
* */
publicclassZipFileDemo{
publicstaticvoidmain(String[] args) throwsIOException{
File file = newFile("d:"+ File.separator + "hello.zip");
ZipFile zipFile = newZipFile(file);
System.out.println("压缩文件的名称为:"+ zipFile.getName());
}
}



【运行结果】:

压缩文件的名称为:d:\hello.zip


现在我们呢是时候来看看如何加压缩文件了,和之前一样,先让我们来解压单个压缩文件(也就是压缩文件中只有一个文件的情况),我们采用前面的例子产生的压缩文件hello.zip

importjava.io.File;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.OutputStream;
importjava.util.zip.ZipEntry;
importjava.util.zip.ZipFile;
/**
* 解压缩文件(压缩文件中只有一个文件的情况)
* */
publicclassZipFileDemo2{
publicstaticvoidmain(String[] args) throwsIOException{
File file = newFile("d:"+ File.separator + "hello.zip");
File outFile = newFile("d:"+ File.separator + "unZipFile.txt");
ZipFile zipFile = newZipFile(file);
ZipEntry entry = zipFile.getEntry("hello.txt");
InputStream input = zipFile.getInputStream(entry);
OutputStream output = newFileOutputStream(outFile);
inttemp = 0;
while((temp = input.read()) != -1){
output.write(temp);
}
input.close();
output.close();
}
}

【运行结果】:

解压缩之前:

这个压缩文件还是175字节

解压之后产生:

又回到了56字节,表示郁闷。


现在让我们来解压一个压缩文件中包含多个文件的情况吧

ZipInputStream类

当我们需要解压缩多个文件的时候,ZipEntry就无法使用了,如果想操作更加复杂的压缩文件,我们就必须使用ZipInputStream类

importjava.io.File;
importjava.io.FileInputStream;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.OutputStream;
importjava.util.zip.ZipEntry;
importjava.util.zip.ZipFile;
importjava.util.zip.ZipInputStream;
/**
* 解压缩一个压缩文件中包含多个文件的情况
* */
publicclassZipFileDemo3{
publicstaticvoidmain(String[] args) throwsIOException{
File file = newFile("d:"+ File.separator + "zipFile.zip");
File outFile = null;
ZipFile zipFile = newZipFile(file);
ZipInputStream zipInput = newZipInputStream(newFileInputStream(file));
ZipEntry entry = null;
InputStream input = null;
OutputStream output = null;
while((entry = zipInput.getNextEntry()) != null){
System.out.println("解压缩"+ entry.getName() + "文件");
outFile = newFile("d:"+ File.separator + entry.getName());
if(!outFile.getParentFile().exists()){
outFile.getParentFile().mkdir();
}
if(!outFile.exists()){
outFile.createNewFile();
}
input = zipFile.getInputStream(entry);
output = newFileOutputStream(outFile);
inttemp = 0;
while((temp = input.read()) != -1){
output.write(temp);
}
input.close();
output.close();
}
}
}

【运行结果】:

被解压的文件:

解压之后再D盘下会出现一个temp文件夹,里面内容:

PushBackInputStream回退流
importjava.io.ByteArrayInputStream;
importjava.io.IOException;
importjava.io.PushbackInputStream;
/**
* 回退流操作
* */
publicclassPushBackInputStreamDemo{
publicstaticvoidmain(String[] args) throwsIOException{
String str = "hello,rollenholt";
PushbackInputStream push = null;
ByteArrayInputStream bat = null;
bat = newByteArrayInputStream(str.getBytes());
push = newPushbackInputStream(bat);
inttemp = 0;
while((temp = push.read()) != -1){
if(temp == ','){
push.unread(temp);
temp = push.read();
System.out.print("(回退"+ (char) temp + ") ");
}else{
System.out.print((char) temp);
}
}
}
}

【运行结果】:

hello(回退,) rollenholt


/**
* 取得本地的默认编码
* */
publicclassCharSetDemo{
publicstaticvoidmain(String[] args){
System.out.println("系统默认编码为:"+ System.getProperty("file.encoding"));
}
}

【运行结果】:

系统默认编码为:GBK


乱码的产生:

importjava.io.File;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.OutputStream;
/**
* 乱码的产生
* */
publicclassCharSetDemo2{
publicstaticvoidmain(String[] args) throwsIOException{
File file = newFile("d:"+ File.separator + "hello.txt");
OutputStream out = newFileOutputStream(file);
byte[] bytes = "你好".getBytes("ISO8859-1");
out.write(bytes);
out.close();
}
}

【运行结果】:

??


一般情况下产生乱码,都是由于编码不一致的问题。

对象的序列化

对象序列化就是把一个对象变为二进制数据流的一种方法。

一个类要想被序列化,就行必须实现java.io.Serializable接口。虽然这个接口中没有任何方法,就如同之前的cloneable接口一样。实现了这个接口之后,就表示这个类具有被序列化的能力。

先让我们实现一个具有序列化能力的类吧:


importjava.io.*;
/**
* 实现具有序列化能力的类
* */
publicclassSerializableDemo implementsSerializable{
publicSerializableDemo(){
}
publicSerializableDemo(String name, intage){
this.name=name;
this.age=age;
}
@Override
publicString toString(){
return"姓名:"+name+"  年龄:"+age;
}
privateString name;
privateintage;
}

这个类就具有实现序列化能力,

在继续将序列化之前,先将一下ObjectInputStream和ObjectOutputStream这两个类

先给一个ObjectOutputStream的例子吧:

importjava.io.Serializable;
importjava.io.File;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.ObjectOutputStream;
/**
* 实现具有序列化能力的类
* */
publicclassPerson implementsSerializable{
publicPerson(){
}
publicPerson(String name, intage){
this.name = name;
this.age = age;
}
@Override
publicString toString(){
return"姓名:"+ name + "  年龄:"+ age;
}
privateString name;
privateintage;
}
/**
* 示范ObjectOutputStream
* */
publicclassObjectOutputStreamDemo{
publicstaticvoidmain(String[] args) throwsIOException{
File file = newFile("d:"+ File.separator + "hello.txt");
ObjectOutputStream oos = newObjectOutputStream(newFileOutputStream(
file));
oos.writeObject(newPerson("rollen", 20));
oos.close();
}
}

【运行结果】:

当我们查看产生的hello.txt的时候,看到的是乱码,呵呵。因为是二进制文件。

虽然我们不能直接查看里面的内容,但是我们可以使用ObjectInputStream类查看:

importjava.io.File;
importjava.io.FileInputStream;
importjava.io.ObjectInputStream;
/**
* ObjectInputStream示范
* */
publicclassObjectInputStreamDemo{
publicstaticvoidmain(String[] args) throwsException{
File file = newFile("d:"+ File.separator + "hello.txt");
ObjectInputStream input = newObjectInputStream(newFileInputStream(
file));
Object obj = input.readObject();
input.close();
System.out.println(obj);
}
}

【运行结果】

姓名:rollen  年龄:20


到底序列化什么内容呢?

其实只有属性会被序列化。

Externalizable接口

被Serializable接口声明的类的对象的属性都将被序列化,但是如果想自定义序列化的内容的时候,就需要实现Externalizable接口。

当一个类要使用Externalizable这个接口的时候,这个类中必须要有一个无参的构造函数,如果没有的话,在构造的时候会产生异常,这是因为在反序列话的时候会默认调用无参的构造函数。

现在我们来演示一下序列化和反序列话:

packageIO;
importjava.io.Externalizable;
importjava.io.File;
importjava.io.FileInputStream;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.ObjectInput;
importjava.io.ObjectInputStream;
importjava.io.ObjectOutput;
importjava.io.ObjectOutputStream;
/**
* 序列化和反序列化的操作
* */
publicclassExternalizableDemo{
publicstaticvoidmain(String[] args) throwsException{
ser(); // 序列化
dser(); // 反序列话
}
publicstaticvoidser() throwsException{
File file = newFile("d:"+ File.separator + "hello.txt");
ObjectOutputStream out = newObjectOutputStream(newFileOutputStream(
file));
out.writeObject(newPerson("rollen", 20));
out.close();
}
publicstaticvoiddser() throwsException{
File file = newFile("d:"+ File.separator + "hello.txt");
ObjectInputStream input = newObjectInputStream(newFileInputStream(
file));
Object obj = input.readObject();
input.close();
System.out.println(obj);
}
}
classPerson implementsExternalizable{
publicPerson(){
}
publicPerson(String name, intage){
this.name = name;
this.age = age;
}
@Override
publicString toString(){
return"姓名:"+ name + "  年龄:"+ age;
}
// 复写这个方法,根据需要可以保存的属性或者具体内容,在序列化的时候使用
@Override
publicvoidwriteExternal(ObjectOutput out) throwsIOException{
out.writeObject(this.name);
out.writeInt(age);
}
// 复写这个方法,根据需要读取内容 反序列话的时候需要
@Override
publicvoidreadExternal(ObjectInput in) throwsIOException,
ClassNotFoundException{
this.name = (String) in.readObject();
this.age = in.readInt();
}
privateString name;
privateintage;
}

【运行结果】:

姓名:rollen  年龄:20

本例中,我们将全部的属性都保留了下来,

Serializable接口实现的操作其实是吧一个对象中的全部属性进行序列化,当然也可以使用我们上使用是Externalizable接口以实现部分属性的序列化,但是这样的操作比较麻烦,

当我们使用Serializable接口实现序列化操作的时候,如果一个对象的某一个属性不想被序列化保存下来,那么我们可以使用transient关键字进行说明:

下面举一个例子:

packageIO;
importjava.io.File;
importjava.io.FileInputStream;
importjava.io.FileOutputStream;
importjava.io.ObjectInputStream;
importjava.io.ObjectOutputStream;
importjava.io.Serializable;
/**
* 序列化和反序列化的操作
* */
publicclassserDemo{
publicstaticvoidmain(String[] args) throwsException{
ser(); // 序列化
dser(); // 反序列话
}
publicstaticvoidser() throwsException{
File file = newFile("d:"+ File.separator + "hello.txt");
ObjectOutputStream out = newObjectOutputStream(newFileOutputStream(
file));
out.writeObject(newPerson1("rollen", 20));
out.close();
}
publicstaticvoiddser() throwsException{
File file = newFile("d:"+ File.separator + "hello.txt");
ObjectInputStream input = newObjectInputStream(newFileInputStream(
file));
Object obj = input.readObject();
input.close();
System.out.println(obj);
}
}
classPerson1 implementsSerializable{
publicPerson1(){
}
publicPerson1(String name, intage){
this.name = name;
this.age = age;
}
@Override
publicString toString(){
return"姓名:"+ name + "  年龄:"+ age;
}
// 注意这里
privatetransientString name;
privateintage;
}

【运行结果】:

姓名:null  年龄:20

最后在给一个序列化一组对象的例子吧:

importjava.io.File;
importjava.io.FileInputStream;
importjava.io.FileOutputStream;
importjava.io.ObjectInputStream;
importjava.io.ObjectOutputStream;
importjava.io.Serializable;
/**
* 序列化一组对象
* */
publicclassSerDemo1{
publicstaticvoidmain(String[] args) throwsException{
Student[] stu = { newStudent("hello", 20), newStudent("world", 30),
newStudent("rollen", 40) };
ser(stu);
Object[] obj = dser();
for(inti = 0; i < obj.length; ++i){
Student s = (Student) obj[i];
System.out.println(s);
}
}
// 序列化
publicstaticvoidser(Object[] obj) throwsException{
File file = newFile("d:"+ File.separator + "hello.txt");
ObjectOutputStream out = newObjectOutputStream(newFileOutputStream(
file));
out.writeObject(obj);
out.close();
}
// 反序列化
publicstaticObject[] dser() throwsException{
File file = newFile("d:"+ File.separator + "hello.txt");
ObjectInputStream input = newObjectInputStream(newFileInputStream(
file));
Object[] obj = (Object[]) input.readObject();
input.close();
returnobj;
}
}
classStudent implementsSerializable{
publicStudent(){
}
publicStudent(String name, intage){
this.name = name;
this.age = age;
}
@Override
publicString toString(){
return"姓名:  "+ name + "  年龄:"+ age;
}
privateString name;
privateintage;
}

【运行结果】:

姓名:  hello  年龄:20

姓名:  world  年龄:30

姓名:  rollen  年龄:40