一、字节缓冲流
1、定义
缓冲区域:采用字节流输入或者输出数据时,用于存放读取或写出的数据,当缓冲区满时一次性输入或输出。
2、作用
提高输入或者输出的效率。输出时可使用手动输出flush()。
可读取或输出任何形式的数据如:文档,图片,音频,视频等。
3、读写步骤
(1)建立源文件路径file1或者目标文件路径file2;
(2)建立字节输入流FileInputStreaminput或FileOutputStream output;
(3)建立输入流缓冲区BufferedInputStreambufferInput或者输出流缓冲区BufferedOutputStream bufferOutput;有两个构造器,可设置缓冲区大小,默认为8192个字节。
(4)建立读取数据的字节数组或需输出的数据源(字符串或者字符数组等)byte[] bytes;
(5)通过缓冲区读取或者输出数据
buffernput.reader();
bufferOutput.writer();
(6)如果时输出数据,输出完毕需要刷新缓冲区:bufferOutput.flush();
(7)关闭流管道,关闭原则:先开的后关,后开的先关。
例题:
public static void test1() {
//创建File对象
File file1 = new File("D:/JavaSE.zip");
File file2 = new File("D:/new_JavaSE.zip");
//创建输入输出流
InputStream in = null;
OutputStream out = null;
//还需要缓冲流
BufferedInputStream buffIn = null;
BufferedOutputStream buffOut = null;
try {
in = new FileInputStream(file1);
//创建缓冲输入流:缓冲区默认大小为8192字节,也可以手动设置缓冲区的大小
buffIn = new BufferedInputStream(in, 8192);
out = new FileOutputStream(file2);
//创建缓冲输出流
buffOut = new BufferedOutputStream(out,8*1024);
//数据的读取操作还是和原来的一样
//读取数据
byte[] buff = new byte[128];
int readLen = 0;
//在读取数据之前获取当前时间
long start = System.currentTimeMillis();//返回系统的当前时间
//循环读取数据
while((readLen = buffIn.read(buff))!=-1) {
//将读取到的数据写出
buffOut.write(buff, 0, readLen);//先写出到缓冲区,等缓冲区装满了之后再一并写出到目的地
}
//手动刷新:将缓冲区的数据强制刷新到目的地
buffOut.flush();
//数据写出完成之后再获取一下系统当前时间
long end = System.currentTimeMillis();
System.out.println("文件复制成功,耗时:"+(end-start)+"毫秒");//不到一秒
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(buffOut!=null) {
try {
buffOut.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(out!=null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(buffIn!=null) {
try {
buffIn.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(in!=null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
二、字符缓冲流
1、定义
缓冲区域:采用字符流输入或者输出数据时,用于存放读取或写出的数据,当缓冲区满时一次性输入或输出。
2、作用
提高输入或者输出的效率。输出时可使用手动输出flush()。
只能用于输入或者输出文本文档。
3、读写步骤
(1)建立源文件路径file1或者目标文件路径file2;
(2)建立字符输入流FileInputStreamreader或FileOutputStream writer;
(3)建立输入流缓冲区BufferedReader bufferReader或者输出流缓冲区BufferedWritter bufferWritter;有两个构造器,可设置缓冲区大小,默认为8192个字节。
(4)建立读取数据的字符数组或需输出的数据源(字符串或者字符数组等)char[] ch;
(5)通过缓冲区读取或者输出数据
bufferReader.reade();
bufferWritter.write();
注意:1)读取时有新增方法:按行读取:String readLine();
2)每输出一行需要换行:newLine();
(6)如果时输出数据,输出完毕需要刷新缓冲区:bufferOutput.flush();
(7)关闭流管道,关闭原则:先开的后关,后开的先关。
public static void test1() {
//创建数据源和目的地的File对象
File file1 = new File("D:/File/bufferedReader.txt");
File file2 = new File("D:/File/new_bufferedReader.txt");
//创建字符缓冲流
BufferedReader br = null;
BufferedWriter bw = null;
try {
br = new BufferedReader(new FileReader(file1));//缓冲区 默认为8192字节
bw = new BufferedWriter(new FileWriter(file2),20*1024);//缓冲区20kb
//读取文件内容
String buff = null;//缓冲读取的数据
int readLen = 0;
//通过循环读取数据
while((buff = br.readLine())!=null) {//readLine()方法会一字符串的形式返回读取到的一行数组,如果数据为空,则返回null
//处理数据
System.out.println(buff);//打印下读取到的数据
//写出数据到目的地
bw.write(buff);
//手动换行
bw.newLine();
}
//刷新流
bw.flush();
System.out.println("文件复制成功");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//关闭流
IOUtil.close(bw,br);
}
}
三、转换流
1、定义
将字节输入流转换为字符输入流;
将字节输出流转换为字符输出流。
2、作用
使用字符流输入或者输出数据时,使用默认的字符集,会产生乱码问题。使用转换流可避免这类问题。
3、读写步骤
(1)建立源文件路径file1或者目标文件路径file2;
(2)使用转换流建立字符输入流FileInputStreamreader或FileOutputStreamWritter writer;同时设置字符集;
reader = new InputStreamReader(file1,”输入字符集”);
writer = new OutputStreamWriter(file2,”输出字符集”);
(3)建立读取数据的字符数组或需输出的数据源(字符串或者字符数组等)char[] ch;
(4)通过转换流读取或者输出数据
reade.read();;
writer.write();
(5)如果时输出数据,输出完毕需要刷新缓冲区:writer.flush();
(6)关闭流管道,关闭原则:先开的后关,后开的先关。
public static void copyFile(File srcFile,File aimFile,String srcCharset,String aimCharset) {
//创建字符转换输入流
InputStreamReader inChange= null;
//创建字符转换输出流
OutputStreamWriter outChange = null;
try {
//字符转换输入流
inChange = new InputStreamReader(new FileInputStream(srcFile), srcCharset);
//字符转换输出流
outChange = new OutputStreamWriter(new FileOutputStream(aimFile), aimCharset);
//创建字符数组,用于读取数据
char[] buffer = new char[512];
//读取字符长度
int readlen = 0;
//循环读取数据
while((readlen=inChange.read(buffer))!=-1) {
//写出
outChange.write(buffer);
System.out.println(Arrays.toString(buffer));
}
//刷新管道
outChange.flush();
System.out.println("文件复制完成");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
OICloseUtil.close(outChange,inChange);
}
}
四、关闭流方法的封装
基本思路:
1、所有的流都共同实现接口closeable,所以可以通过closeable超类接收各种流。
2、因为流的数量不定,使用可变参数传入。
public static void close(Closeable ...objs){//参数:需要能够接收多个流对象
//遍历objs,获取所有的流对象,然后关闭
for(Closeable obj:objs) {
if(obj!=null){
//流对象不为null,则关闭流
try{
obj.close();
}catch (IOException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
五、设计模式(单例模式)
单例模式分为饿汉模式和懒汉模式。其作用时用来确保该类运行时只存在该类的一个实例。
1、饿汉模式
基本思想:不管需不需要该类的实例,先创建一个该类的实例放着。需要用的时候可以直接用。
基本操作:将该类的属性和构造器均私有化并设置为静态属性,仅暴露一个方法,返回该类的仅有的这个实例。
class Singleton{
//自己来创建一个实例:通过设置静态属性来创建该类的实例
privatestatic Singleton instence = new Singleton();//类加载时就创建一个实例
//私有化构造器:禁止外部创建该类的实例
private Singleton() {};
//获取创建的实例
public static Singleton getInstance() {
//返回创建好的实例
return instence;
}
}
2、懒汉模式
基本思想:先不创建实例,等外部需要时再创建该类的实例。
基本操作:将该类的属性和构造器均私有化并设置为静态属性,通过判断该类的实例是否存在,不存在时才创建。
class Singleton2{
//定义静态属性
privatestatic Singleton2 instance = null;//先不创建实例
//私有化构造器
privateSingleton2() {}
//外部需要时,再通过方法阿里创建实例并返回
publicstatic Singleton2 getInstance() {
//先判断是否以及存在该实例
if(instance== null) {
//创建实例
instance= new Singleton2();
}
returninstance;
}
}