1.BufferedInputStream与BufferedOutputStream类
BufferedInputStream类可以对所有InputStream类进行带缓存区的包装以达到性能的优化。
BufferedInputStream类有两个构造方法:
BufferedInputStream(InputStream in)
BufferedInputStream(InputStream in,int size)
第一种形式的构造方法创建了一个带有32个字节的缓存流;第二种形式的构造方法按指定的大小来创建缓存区。一个最优的缓存区的大小,取决于它所在的操作系统、可用的内存空间以及机器配置。从构造方法可以看出,BufferedInputStream对象位于InputStream类对象之前。
BufferedOutputStream的构造方法和BufferedInputSream类似
注意:flush()方法就是用于即使在缓存区没有满的情况下,也将缓存区的内容强制写入外设。习惯上称这个过程为刷新。flush()方法只对使用缓存区的OutputStream类的子类有效。当调用close()方法时,系统在关闭流之前,也会将缓存区中的信息刷新到磁盘文件中。
2.BufferedReader与BufferedWriter类
BufferedReader类与BufferedWriter类分别继承Reader类和Writer类。这两个类同样具有内部缓存机制,并可以以行为单位进行输入/输出。
BufferedReader常用的方法如下:
int read() 读取单个字符。
int read(char[] cbuf,int off,int len) 将字符读入到数组的某一部分。返回读取的字符数。达到尾部 ,返回-1。
String readLine() 读取一个文本行。
void close() 关闭该流。并释放与该流相关的所有资源。
BufferedWriter常用方法如下:
void write(char ch) 写入单个字符。
void write(char []cbuf,int off,int len) 写入字符数据的某一部分。
void write(String s,int off,int len) 写入字符串的某一部分。
void newLine() 写入一个行分隔符。
void flush() 刷新该流中的缓冲。将缓冲数据写到目的文件中去。
void close() 关闭此流,再关闭前会先刷新它。
import java.io.*;
public class BufferReader_and_BufferWriter {
public static void main(String[] args) {
String content[]={"你站在桥上看风景", "看风景的人在楼上看你", "明月装饰了你的窗子", "你装饰了别人的梦" };
File file=new File("C:\\Users\\liuyue\\Desktop\\test.txt");
try {
FileWriter fileWriter=new FileWriter(file);
BufferedWriter bufferedWriter=new BufferedWriter(fileWriter);
for (int i=0;i<content.length;i++){
bufferedWriter.write(content[i]);
bufferedWriter.newLine();
}
bufferedWriter.flush();
bufferedWriter.close();
fileWriter.close();
}catch (Exception e){
System.out.println(e);
}
try {
FileReader fileReader=new FileReader(file);
BufferedReader bufferedReader=new BufferedReader(fileReader);
String s=null;
int i=0;
while ((s=bufferedReader.readLine())!=null){
i++;
System.out.println("第"+i+"行:"+s);
}
bufferedReader.close();
fileReader.close();
}catch (Exception e){
System.out.println(e);
}
}
}
3.DataInputSteam和DataOutputStream类
DataInputStream和DataOutputStream类允许应用程序以机器无光的方式从底层输入流中读取基本java数据类型。也就是说,当读取一个数据时,不必再关心这个数值应当是哪种字节。
两者的构造方法也大同小异:
DataInputStream(InputStream in)
DataOutputStream(OutputStream out)
DataInputStream的主要方法有:
int read(byte[] b) 从输入流中读取一定的字节,存放到缓冲数组b中。返回缓冲区中的总字节数。
int read(byte[] buf,int off,int len) 从输入流中一次读入len个字节存放在字节数组中的偏移off个字节及后面位置。
String readUTF() 读入一个已使用UTF-8修改版格式编码的字符串
String readLine() 读入一行
boolean readBoolean 读取一个boolbean类型的值
int readInt() 读取一个int类型的值
byte readByte() 读取一个byte类型的值
char readChar() 读取一个char类型的值
DataOutputStream的方法主要有:
void write(byte[] b,int off,int len) 将byte数组off角标开始的len个字节写到OutputStream 输出流对象中。
void write(int b) 将指定字节的最低8位写入基础输出流。
void writeBoolean(boolean b) 将一个boolean值以1-byte形式写入基本输出流。
void writeByte(int v) 将一个byte值以1-byte值形式写入到基本输出流中。
void writeBytes(String s) 将字符串按字节顺序写入到基本输出流中。
void writeChar(int v) 将一个char值以2-byte形式写入到基本输出流中。先写入高字节。
void writeInt(int v) 将一个int值以4-byte值形式写入到输出流中先写高字节。
void writeUTF(String str) 以机器无关的的方式用UTF-8修改版将一个字符串写到基本输出流。该方法先用writeShort写入两个字节表示后面的字节数。
int size() 返回written的当前值。
在这里我写了一段程序来了解每个方法,在读取中文字符时需要小心一些避免出现乱码。
在使用循环读取的时候,当读到最后会抛出EOFException错误来提示你读完了。我注释的地方智能一部分一部分的解开,不然会发成错误,因为前面的方法把东西读完了后面的方法就无法读取到东西了
import java.io.*;
public class DataInputStream_and_DataOutputStream {
public static void main(String[] args) {
try {
FileOutputStream fileOutputStream=new FileOutputStream("C:\\Users\\liuyue\\Desktop\\test.txt");
DataOutputStream dataOutputStream=new DataOutputStream(fileOutputStream);
dataOutputStream.writeUTF("使用writeUTF()方法写入数据");
dataOutputStream.writeChars("使用writeChars()方法写入数据");
dataOutputStream.writeBytes("使用writeBytes()方法写入数据");
dataOutputStream.writeBoolean(true);
dataOutputStream.writeInt(666);
dataOutputStream.write("使用write()方法写入数据".getBytes());
dataOutputStream.close();
fileOutputStream.close();
FileInputStream fileInputStream=new FileInputStream("C:\\Users\\liuyue\\Desktop\\test.txt");
DataInputStream dataInputStream=new DataInputStream(fileInputStream);
// System.out.println(dataInputStream.readUTF());
// char[] chars=new char[1024];
// char c;
// int i=0;
// try {
// while ((c=dataInputStream.readChar())!=-1) {
// chars[i]=c;
// i++;
// }
// }catch (EOFException e){
// System.out.println("读完了!");
// }
// String string=new String(chars);
// System.out.println(string);
// byte[] bytes=new byte[1024];
// byte b;
// int i=0;
// try {
// while ((b=dataInputStream.readByte())!=-1){
// bytes[i]=b;
// i++;
// }
// }catch (EOFException e){
// System.out.println("读完了!");
// }
// String s=new String(bytes);
// System.out.println(s);
// byte[] bytes=new byte[1024];
// int len=0;
// try {
// len =dataInputStream.read(bytes);
// }catch (EOFException e){
// System.out.println("读完了");
// }
// System.out.println(new String(bytes,0,len));
dataInputStream.close();
fileInputStream.close();
}catch (Exception e){
System.out.println(e);
}
}
}
4.ZipInputStream和ZipOutputStream类
JAVA实现了I/O数据流与网络数据流的单一接口,因此数据的压缩、网络传输和解压缩的实现比较容易。ZipEntry类产生的对象是用来代表一个ZIP文件内的进入点。ZipInputStream类用来读去ZIP压缩格式的文件,所支持的包括已压缩及未压缩的进入点。ZipOutputStream类用来写出ZIP压缩格式的文件,而且所支持的包括已压缩及未压缩的进入点。
ZipOutputStream(OutputStream out)
常用方法有:
void putNexEntry(ZipEntry e) 开始写一个新的ZipEntry,并将流内的位置移至此entry所指数数据的开头
void write(byte[] b,int off,int len) 将字节数组写入当前ZIP条目数据
void finish() 完成写入ZIP输出流的内容,无需关闭它所配合的OutputStream
void setComment(String comment) 可设置此ZIP文件的注释文字
在写这个程序时,我碰到了一个坑,就是重复压缩长路径,压缩出来的文件是这样的:
后来写了一个方法改变压缩的路径名才得以解决:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class ZipOutputStream_test {
private void zip(String zipFileName, File inputFile) throws Exception{
ZipOutputStream zipOutputStream=new ZipOutputStream(new FileOutputStream(zipFileName));
zip(zipOutputStream,inputFile,"");
zipOutputStream.flush();
zipOutputStream.close();
}
private void zip(ZipOutputStream zipOutputStream, File inputFile, String base) throws Exception {
if (inputFile.isDirectory()){
File[] files=inputFile.listFiles();
if (base.length()!=0){
zipOutputStream.putNextEntry(new ZipEntry(base+"/"));
}
for (int i=0;i<files.length;i++){
zip(zipOutputStream,files[i],base+getLocation(""+files[i]));
}
}else {
zipOutputStream.putNextEntry(new ZipEntry(base));
FileInputStream inputStream=new FileInputStream(inputFile);
int b;
System.out.println(base);
while ((b=inputStream.read())!=-1){
zipOutputStream.write(b);
}
inputStream.close();
}
}
private String getLocation(String s){
String[] stringList=s.replace("\\","/").split("/");
int len=stringList.length;
String string="\\"+stringList[len-1];
return string;
}
public static void main(String[] args) {
ZipOutputStream_test zipOutputStreamStreamTest=new ZipOutputStream_test();
try {
long oldTime=System.currentTimeMillis();
zipOutputStreamStreamTest.zip("C:\\Users\\liuyue\\Desktop\\test.zip",new File("C:\\Users\\liuyue\\Desktop\\longfei"));
long currentTime=System.currentTimeMillis();
float time=(float)(currentTime-oldTime)/1000;
System.out.println("压缩完成,耗时"+time+"s");
}catch (Exception e){
System.out.println(e);
}
}
}
从这端程序可以看出,每一个ZIP文件中可能包含多个文件,使用ZipOutputStream类将文件写入目标ZIP时,必须先使用ZipOutputStream对象的putNexEntry()方法,写入个别文件的entry,将流内目标制定的位置移到该rntry所指的开头位置。
说完了压缩再来说解压缩,解压缩就简单了
ZipInputStream(InputStream in)
常用方法:
int read(byte[] b,int off,int len) 读取目标b数组内off偏移量的位置,长度是N的字节
int available() 判断是否已读完目前entry所指定的数据。已读完返回0,否则返回1
void closeEntry() 关闭当前ZIP条目并定位流以读取下一个目录
long skip(long n) 跳过当前ZIP条目中指定的字节数
ZipEntry getNexEntry() 读取下一个ZipEntry,并将流内的位置移至该entry所指数据的开头
ZipEntry createZipEntry(String name) 以指定的name参数新建一个ZipEntry对象
import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
public class ZipInputStream_test {
public static void main(String[] args) {
File file=new File("C:\\Users\\liuyue\\Desktop\\test.zip");
ZipInputStream zipInputStream;
try {
ZipFile zipFile=new ZipFile(file);
zipInputStream=new ZipInputStream(new FileInputStream(file));
ZipEntry zipEntry=zipInputStream.getNextEntry();
while (((zipEntry=zipInputStream.getNextEntry())!=null)&&!zipEntry.isDirectory()){
File tmp=new File("C:\\Users\\liuyue\\Desktop\\"+zipEntry.getName());
if (!tmp.exists()){
tmp.getParentFile().mkdir();
OutputStream outputStream=new FileOutputStream(tmp);
InputStream inputStream=zipFile.getInputStream(zipEntry);
int count=0;
while ((count=inputStream.read())!=-1){
outputStream.write(count);
}
outputStream.close();
inputStream.close();
}
zipInputStream.closeEntry();
System.out.println(zipEntry.getName()+"解压成功");
}
zipInputStream.close();
}catch (Exception e){
System.out.println(e);
}
}
}