IO流技术

1.IO流的基本概念

1.1流的原理

在这里插入图片描述
1)在Java程序中,对于数据的输入/输出操作以“流”(stream)方式进行。
2)J2SDK提供了各种各样的“流”类,用以获取不同种类的数据;程序中通过标准的方法输入或输出数据。
3)Java的流类型一般位于java.io包中

1.2流的概念

数据源

  1. data source.提供原始数据的原始媒介。常见的:数据库、文件、其他程序、内存、网络连接、IO设备。
    2)数据源就像水箱,流就像水管中流着的水流,程序就是我们最终的用户。流是一个抽象、动态的概念,是一连串连续动态的数据集合。
    在这里插入图片描述

2.流的细分和体系_四大抽象类

2.1流的分类

流的方向:
1)输入流:数据源到程序(InputStream、Reader读进来)
2)输出流:程序到目的地(OutPutStream、Writer写出去)
处理数据单元:
1)字节流:按照字节读取数据(InputStream、OutputStream)
2)字符流:按照字符读取数据(Reader、Writer)
在这里插入图片描述
注意:输入输出是相对于程序而言,而不是相对于源和目标而言
功能不同:
1)节点流:可以直接从数据源或目的地读写数据。
2)处理流(包装流):不直接连接到数据源或目的地,是其他流进行封装。目的主要是简化操作和提高性能。
节点流和处理流的关系:
1)节点流处于io操作的第一线,所有操作必须通过他们进行;
2)处理流可以对其他流进行处理(提高效率或操作灵活性)。
在这里插入图片描述

2.2IO流的体系

1)InputStream和OutputStream
Java语言中最基本的两个字节输入输出类。
其他所有字节输入输出流类都继承自这两个基类。
这两个类都是抽象类,不能创建它们的实例,只能使用它们的子类
在这里插入图片描述
2)Reader和Writer
Java语言中最基本的两个字符输入输出类。
其他所有字符输入输出流类都继承自这两个基类
这两个类都是抽象类,不能创建它们的实例,只能使用它们的子类
在这里插入图片描述

3.文件字节流

3.1FileInputStream/FileOutputStream

使用FileInputStream读取文件内容
1)abstract int read();
2)int read(byte b[]);
3)int read(byte b[],int off,int len);
4)int available();
5)close();

public class TestInputStream {
	public static void main(String[] args) throws IOException {
		//(1)数据源于应用程序之间搭建管道
		FileInputStream fis = new FileInputStream(new File("D:\\test.txt"));
		//(2)从数据源开始向程序中读数据
		int count = fis.available();
		System.out.println(count);
		//中转站比较小,一次读一个字节
		//System.out.println(fis.read());
		//System.out.println(fis.available());
		int buf = 0;//存储读到的字节
		int i = 0;
		while((buf=fis.read()) != -1) {
			i++;
			System.out.print((char)buf);
		}
		System.out.println();
		//(3)关闭
		fis.close();
		System.out.println(i);
	}
}
public class TestInputStream2 {
	public static void main(String[] args) throws IOException {
		//(1)搭桥
		FileInputStream fis = new FileInputStream("D:\\test.txt");
		//(2)创建大一些的中转站
		byte[] buf = new byte[1024];
		int len = 0;//用于存储每次读到的实际字节
		int i = 0;
		while ((len = fis.read(buf)) != -1) {
			i++;
			System.out.println(new String(buf,0,len));
		}
		//(3)关闭
		fis.close();
		System.out.println(i);
	}
}	

使用FileOutputStream写内容到文件
1)abstract void write(int b);
2)void write(byte b[]);
3)void write(byte b[],int off,int len);
4)void flush();
5)void close();

public class TestFileOutputStream {
	public static void main(String[] args) {
		//(1)搭桥
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream("D:\\a.txt",true);//true如果磁盘上有文件,而且文件有内容,将在原来的内容的基础上进行追加
			//(2)写数据,一次写一个字节
			//fos.write(97);
			//(3)一次写多个字节
			byte[] buf = "helloworld".getBytes();
			fos.write(buf);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			//(3)关闭
			try {
				if (fos != null) {
					fos.close();
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}		
	}
}

4.使用字节流实现文件复制

4.1文件复制的原理

在这里插入图片描述

public class TestFileCopy {
	public static void main(String[] args) {
		//数据源是文件
		FileInputStream fis = null;
		//目的地
		FileOutputStream fos = null;
		try {
			fis = new FileInputStream("D:\\test.txt");
			fos = new FileOutputStream("D:\\test2.txt");
			
			byte[] buf = new byte[1024];
			int len = 0;
			while((len=fis.read(buf))!=-1) {
				fos.write(buf, 0, len);
			}
			/*
			int b = 0;
			while ((b = fis.read())!=-1) {
				fos.write(b);
			}
			*/
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			if(fis != null) {
				fis.close();
			}	
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			if(fos != null) {
				fos.close();
			}		
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

5.文件字符流

5.1Reader/Writer

使用Reader读取文件内容
1)int read();
2)int read(char[] cbuf)
3)int read(char[] cbuf,int off,int len);
4) int available();
5)close();

public class TestFileReader {
	public static void main(String[] args) throws IOException {
		//(1)搭桥
		FileReader reader = new FileReader("D:\\test.txt");
		//(2)读取
		//int b = reader.read();//读到的字符的int类型 数据
		//System.out.println((char)b);
		
		/*
		int b = 0;
		while ((b = reader.read()) != -1) {
			System.out.print((char)b);
		}
		*/
		
		char[] ch = new char[1024];
		int len = 0;
		while ((len = reader.read(ch)) != -1) {
			System.out.println(new String(ch,0,len));
		}
		reader.close();
	}
}

使用Writer写内容到文件
1)void write(int c);
2)void write(char[] cbuf);
3)abstract void write(char[] cbuf,int off,int len);
4)void write(String str);
5) abstract void flush();
6)void close();

public class TestWriter {
	public static void main(String[] args) {
		//创建对象
		FileWriter write = null;
		try {
			write = new FileWriter("D:\\b.txt");
			//写数据
			write.write("你好吗?");//写到了缓冲区中
			write.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			//关闭
			if (write != null) {
				try {
					write.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}	
	}
}

6.缓冲字节流_缓冲字符流

6.1缓冲字节流

BufferedInputStream和BufferedOutputStream
FileInputStream和FileOutputStream是节点流
在这里插入图片描述
BufferedInputStream和BufferedOutputStream是处理流(包装流)

  1. 读文件和写文件都使用了缓冲区,减少了读写次数,从而提高了效率
  2. 当创建这两个缓冲流的对象时,会创建内部缓冲数组,缺省使用32字节大小的缓冲区
  3. 当读取数据时,数据按块读入缓冲区,其后的读操作则直接访问缓冲区
  4. 当写入数据时,首先写入缓冲区,当缓冲区满时,其中的数据写入所连接的输出流。使用方法flush()可以强制将缓冲区的内容全部写入输出流。
  5. 关闭流的顺序和打开流的顺序相反。只要关闭高层流即可,关闭高层流其实关闭了底层节点流。
  6. Flush的使用:手动将buffer中内容写入文件。

在这里插入图片描述

public class TestCopy {
	public static void main(String[] args) {
		//(1)数据源
		FileInputStream fis = null;
		//(2)目的地
		FileOutputStream fos = null;
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		
		try {
			fis = new FileInputStream("D:\\jdk api 1.8_google.CHM");
			fos = new FileOutputStream("D:\\jdk api 1.8_google2.CHM");
			
			bis = new BufferedInputStream(fis);
			bos = new BufferedOutputStream(fos);
			byte[] b = new byte[1024];
			int len = 0;
			long start = System.currentTimeMillis();
			while ((len=bis.read(b)) != -1) {
				bos.write(b, 0, len);
			}
			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 {
			//关闭
			try {
				if(bos != null) {
					bos.close();
				}
				
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try {
				if (bis != null) {
					bis.close();
				}	
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}		
	}
}

6.2缓冲字符流

BufferedReader
readLine() 读取一个文本行的数据
BufferedWriter
newLine():写入一个行分隔符
使用缓冲字符流是复制文本文件常用的方式

public class TestBuffered {
	public static void main(String[] args) {
		//缓冲字符流
		BufferedReader br = null;
		BufferedWriter bw = null;
		try {
			br = new BufferedReader(new FileReader("D:\\a.txt"));
			bw = new BufferedWriter(new FileWriter("D:\\copya.txt"));
			
			String line = null;//用于存储读到的字符串
			while ((line = br.readLine()) != null) {
				bw.write(line);
				bw.newLine();
				bw.flush();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			if (bw != null) {
				bw.close();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			if (br != null) {
				br.close();
			}		
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

7.转换流

7.1InputStreamReader和OutputStreamWriter

处理流
用于将字节流转化成字符流,字符流与字节流之间的桥梁。
InputStreamReader的作用是把InputStream装换成Reader
OutputStreamWriter的作用是把OutputStream装换成Writer

存在将字节流装换成字符流的装换流,因为字符流操作文本更简单
不存在把字符流装换成字节流的装换流,因为没有必要
System.in代表标准输入,即键盘输入,是InputStream的实例

public class Test {
	public static void main(String[] args) {
		//任务需求,从键盘获取数据,写入磁盘文件
		//(1)数据源是标准的输入设备,键盘System.in
		//(3)提高读取效率
		BufferedReader br = null;
		//(4)提高写入效率
		BufferedWriter bw = null;
		try {
			InputStream is = System.in;
			//(2)需要使用转换流,装换成字符流
			InputStreamReader isr = new InputStreamReader(is,"gbk");
			br = new BufferedReader(isr);
			bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("D:\\systein.txt"),"gbk"));
			//(5)写入磁盘文件
			String line = null;
			while (!"over".equals(line=br.readLine())){
				bw.write(line);
				bw.newLine();
				bw.flush();
			}
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			if (bw != null) {
				try {
					bw.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}	
		}	
	}
}

8.打印流

8.1PrintStream

1)PrintStream提供了一系列的print()和println(),可以实现将基本数据类型格式化成字符串输出。对象类型先调用toString(),然后输出该方法返回的字符串。
2)System.out就是PrintStream的一个实例,代表显示器
3)System.err也是PrintStream的一个实例,代表显示器
4)PrintStream的输出功能非常强大,通常需要输出文本内容,都可以将输出流包装成PrintStream后进行输出。
5)PrintSteam的方法都不抛出IOException

8.2PrintWriter

1)PrintStream的对应字符流,功能相同,方法对应。
2)PrintWriter的方法也不抛出IOException
3)复制文件时可以使用PriWriter代替BufferedWriter完成,更简单。

public class Test {
	public static void main(String[] args) throws IOException {
		//PrintStream ps = System.out;
		//PrintStream ps = System.err;
		//PrintStream ps = new PrintStream(new FileOutputStream("D:\\print.txt"));
		PrintWriter ps = new PrintWriter(new FileOutputStream("D:\\print1.txt"));
		//无需类型转换,自动转成String类型
		ps.println("hello");
		ps.println(true);
		ps.println(19);
		ps.println(98.5);
		ps.println(new Date(1000));
		ps.flush();
		ps.close();
		//只能写入字符串类型
		BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\a.txt"));
		bw.write("helloworld");
		bw.flush();
		bw.close();
	}
}

9.数据流

9.1DataInputStream和DataOutputStream

1)提供了可以存取所有Java基础类型数据(如:int,double等)和String的方法。
2)处理流,只针对字节流,二进制文件
3)输入流链和输出流链
4)注意:只要关闭上层流即可
在这里插入图片描述

public class Test {
	public static void main(String[] args) throws IOException {
		write();
		read();
	}
	//读数据的方法
	public static void read() throws IOException {
		//数据源
		FileInputStream fis = new FileInputStream(new File("D:\\data.txt"));
		//
		BufferedInputStream bis = new BufferedInputStream(fis);
		//
		DataInputStream dis = new DataInputStream(bis);
		System.out.println(dis.readInt());
		System.out.println(dis.readDouble());
		System.out.println(dis.readBoolean());
		System.out.println(dis.readChar());
		System.out.println(dis.readUTF());
		dis.close();
				
	}
	//写数据的方法
	public static void write() throws IOException {
		/*
		//目的地
		FileOutputStream fos = new FileOutputStream(new File("D:\\data.txt"));
		//缓冲流提高写入效率
		BufferedOutputStream bos = new BufferedOutputStream(fos);
		//数据流,增加对java基本基本数据类型和String的处理
		DataOutputStream dos = new DataOutputStream(bos);
		*/
		DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(new File("D:\\data.txt"))));
		//写入数据
		dos.writeInt(98);
		dos.writeDouble(98.5);
		dos.writeBoolean(true);
		dos.writeChar('a');
		dos.writeUTF("helloworld");
		//关闭流
		if(dos != null) {
			dos.close();
		}
	}
}

10.对象流

10.1对象xu序列化(Serialization)

ObjectOutputStream—>序列化—>写对象,将对象以“二进制/字节”的形式写到(文件)
ObjectInputStream —>反序列化—>读对象

将Java对象转换成字节序列(IO字节流)
对象反序列化(DeSerialization)
从字节序列中恢复Java对象

10.2为什么序列化

序列化以后的对象可以保存到磁盘上,也可以在网络上传输,使得不同的计算机可以共享对象。(序列化的字节序列是平台无关的)

10.3对象序列化的条件

只有实现了Serializable接口的类的对象才可以被序列化。
Serializable接口中没有任何的方法,实现该接口的类不需要实现额外的方法。
如果对象的属性时对象,属性对应类也必须实现Serializable接口

10.4如何实现序列化

创建ObjectOutputStream对象
调用writeObject()输出对象

10.5如何实现反序列化

创建ObjectInputStream对象
调用readObject()读取对象

public class Person implements Serializable{
	private String name;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public Person() {
		super();
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}	
}

public class Test {
	public static void main(String[] args) {
		//write();
		read();
	}
	//读对象的方法
	public static void read() {
		ObjectInputStream ois = null;
		try {
			ois = new ObjectInputStream(new FileInputStream("D:\\object.txt"));
			System.out.println(ois.readInt());
			System.out.println(ois.readUTF());
			Person p = (Person)ois.readObject();
			System.out.println(p);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			if(ois != null) {
				try {
					ois.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}	
		}		
	}
	//写对象的方法
	public static void write() {
		//创建对象流对象
		ObjectOutputStream oos = null;
		try {
			oos = new ObjectOutputStream(new FileOutputStream("D:\\object.txt"));
			oos.writeInt(98);
			oos.writeUTF("hello");
			oos.writeObject(new Person("marry",18));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			if(oos != null) {
				try {
					oos.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}		
	}
}

11.序列化和反序列化

11.1序列化与反序列化

1)序列化能保存的元素
a)只能保存对象的非静态成员变量
b)不能保存任何成员方法和静态的成员变量
c)不保存transient成员变量
d)如果一个对象的成员变量是一个对象,这个对象的成员变量也会保存
e)序列化保存的只是变量的值,对于变量的任何修饰符,都不能保存
2)使用对象流把一个对象写到文件时不仅保证该对象时序列化的,而且该对象的成员对象也必须是可序列化的
3)如果一个可序列化的对象包含对某个不可序列化的对象的引用,那么整个序列化操作将会失败,并且会抛出一个NotSerializableException。我们可以将这个引用标记为transient,那么对象仍然可以序列化。

11.2对象序列化注意事项

1)同一个对象多次序列化的处理
a)所有保存到磁盘中的对象都有一个序列化编号
b)序列化一个对象中,首先检查该对象是否已经序列化过
c)如果没有,进行序列化
d)如果已经序列化,将不再重新序列化,而是输出编号即可
2)如果不希望某些属性序列化,或不希望出现递归序列
a)为属性添加transient关键字(完成排除在序列化之外)
b)自定义序列化(不仅可以决定哪些属性不参加序列化,还可以定义属性具体如何序列化)
3)序列化版本不兼容
a)修改了实例属性后,会影响版本号,从而导致反序列化不成功
b)解决方案:为Java对象指定序列化版本号serialVersionUID

public class Student implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private String name;
	private int age;
	public static String school;
	private transient String pwd;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getPwd() {
		return pwd;
	}
	public void setPwd(String pwd) {
		this.pwd = pwd;
	}
	public Student(String name, int age, String pwd) {
		super();
		this.name = name;
		this.age = age;
		this.pwd = pwd;
	}
	public Student() {
		super();
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + ", pwd=" + pwd + "]" + "School =" + school;
	}
}
public class Test {	
	public static void main(String[] args) {
		//write();
		read();	
	}
	public static void read() {
		ObjectInputStream ois = null;
		try {
			ois = new ObjectInputStream(new FileInputStream("D:\\Object2.txt"));
			Student stu = (Student)ois.readObject();
			System.out.println(stu);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if(ois != null) {
				try {
					ois.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}	
	}
	public static void write() {
		ObjectOutputStream oos = null;
		try {
			oos = new ObjectOutputStream(new FileOutputStream("D:\\Object2.txt"));
			Student stu = new Student("marry",18,"888888");
			Student.school = "java";
			oos.writeObject(stu);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (oos != null) {
				try {
					oos.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

}
public class Classes implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private String name;
	private ArrayList<Student> al;
	private String school;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public ArrayList<Student> getAl() {
		return al;
	}
	public void setAl(ArrayList<Student> al) {
		this.al = al;
	}
	public Classes(String name, ArrayList<Student> al) {
		super();
		this.name = name;
		this.al = al;
	}
	public Classes() {
		super();
	}
	@Override
	public String toString() {
		return "Classes [name=" + name + ", al=" + al + "]";
	}
	
}
public class TestClasses {
	public static void write() {
		ArrayList<Student> al = new ArrayList<Student>();
		al.add(new Student("marry",18,"888888"));
		al.add(new Student("jack",20,"123456"));
		al.add(new Student("lili",22,"654321"));
		
		Classes cl = new Classes("1班",al);
		
		ObjectOutputStream oos = null;
		try {
			oos = new ObjectOutputStream(new FileOutputStream("D:\\classes.txt"));
			oos.writeObject(cl);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if(oos != null) {
				try {
					oos.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
	public static void read() {
		ObjectInputStream ois = null;
		try {
			ois = new ObjectInputStream(new FileInputStream("D:\\classes.txt"));
			Classes cla = (Classes) ois.readObject();
			System.out.println(cla);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (ois != null) {
				try {
					ois.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}		
	}
	public static void main(String[] args) {
		//write();
		read();
	}
}

12.文件夹的复制

12.1复制文件夹

字节流 字符流
BufferedInputStream,BufferedOutputStream FileInputStream,FileOutputStream
问题分解
1)复制一个文件
2)指定目录下的所有文件
3)指定目录下的所有文件及子目录下的所有文件

public class TestCopy {
	public static void main(String[] args) {
		/*File srcFile = new File("D:\\360极速浏览器下载\\太子妃升职记.torrent");
		File targetFile = new File("D:\\太子妃升职记.torrent");
		copyFile(srcFile,targetFile);
		*/
		File srcDir= new File("D:\\360极速浏览器下载");
		File targetDir = new File("C:\\360极速浏览器下载");
		copyDir(srcDir,targetDir);
	}
	public static void copyDir(File srcDir,File targetDir) {
		if (!targetDir.exists()) {
			targetDir.mkdir();//如过目的地不存在,则需要使用File类的方法进行创建
		}
		File[] files = srcDir.listFiles();//获取指定目录下的所有File对象
		for (File file : files) {
			if (file.isFile()) {
				copyFile(new File(srcDir+"\\"+file.getName()),new File(targetDir+"\\"+file.getName()));
			}else {
				copyDir(new File(srcDir+"\\"+file.getName()),new File(targetDir+"\\"+file.getName()));
			}
		}
	}
	public static void copyFile(File srcFile,File targetFile) {
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		try {
			bis = new BufferedInputStream(new FileInputStream(srcFile));
			bos = new BufferedOutputStream(new FileOutputStream(targetFile));
			
			byte[] buf = new byte[1024];
			int len = 0;
			while ((len=bis.read(buf)) != -1) {
				bos.write(buf, 0, len);	
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (bos != null) {
				try {
					bos.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if (bis != null) {
				try {
					bis.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}			
	}
}

13.字节数组流

13.1ByteArrayInutStream 和 ByteArrayOutputStream

1)数据源或目的地为:字节数组
2)只有字节流,没有字符流
3)节点流

public class Test {
	public static void main(String[] args) {
		byte[] buf = write();
		read(buf);
	}
	public static void read(byte[] buf) {
		ObjectInputStream ois = null;
		try {
			ByteArrayInputStream bais = new ByteArrayInputStream(buf);
			ois = new ObjectInputStream(bais);
			
			System.out.println(ois.readInt());
			System.out.println(ois.readDouble());
			System.out.println(ois.readChar());
			System.out.println(ois.readBoolean());
			System.out.println(ois.readObject());
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if(ois != null) {
				try {
					ois.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}			
	}
	public static byte[] write() {
		//创建字节数组流对象
		ByteArrayOutputStream bas = null;
		ObjectOutputStream oos = null;
		try {
			bas = new ByteArrayOutputStream();
			oos = new ObjectOutputStream(bas);
			
			oos.writeInt(98);
			oos.writeDouble(98.5);
			oos.writeChar('a');
			oos.writeBoolean(true);
			oos.writeObject(new Date(1000));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (oos != null) {
				try {
					oos.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return bas.toByteArray();
	}
}

14.设计模式_装饰器模式

14.1装饰器模式Decorator

职责:动态的为一个对象增加新的功能
装饰模式是一种用于代替继承的技术,无须通过继承增加子类就能扩展对象的新功能。使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。
在这里插入图片描述
实现细节
1)抽象构件角色 ICar
2)具体的构件角色 Car
3)装饰器角色 SuperCar
4)具体的装饰器角色 FlyCar、WaterCar、AICar

public interface ICar {
	void move();
}
public class Car implements ICar{

	@Override
	public void move() {
		System.out.println("汽车可以在陆地上行驶");		
	}
	
}
public class SuperCar implements ICar{
	private ICar car;
	public SuperCar(ICar car) {
		super();
		this.car = car;
	}
	@Override
	public void move() {
		// TODO Auto-generated method stub
		car.move();
	}
}
public class FlyCar extends SuperCar{

	public FlyCar(ICar car) {
		super(car);
		// TODO Auto-generated constructor stub
	}
	public void move() {
		super.move();
		this.fly();
	}
	public void fly() {
		System.out.println("汽车可以飞行,因为有翅膀");
	}
}
public class WaterCar extends SuperCar{
		public WaterCar(ICar car) {
			super(car);
			// TODO Auto-generated constructor stub
		}
		public void move() {
			super.move();
			this.water();
		}
		public void water() {
			System.out.println("汽车可以潜水");
		}
}
public class AICar extends SuperCar{

	public AICar(ICar car) {
		super(car);
		// TODO Auto-generated constructor stub
	}
	
	@Override
	public void move() {
		// TODO Auto-generated method stub
		super.move();
		this.autoDrive();
	}
	private void autoDrive() {
		// TODO Auto-generated method stub
		System.out.println("可以自动驾驶");
	}
}
public class Test {
	public static void main(String[] args) {
		ICar car = new Car();
		car.move();
		System.out.println("\n为汽车增加新的功能");
		FlyCar fly = new FlyCar(car);
		fly.move();
		
		System.out.println("\n再为汽车增加自动驾驶的功能");
		AICar ai = new AICar(fly);
		ai.move();
		
		AICar ai2 = new AICar(new FlyCar(new Car()));
		ai2.move();
		
		System.out.println("各种组合");
		WaterCar water=new WaterCar(new FlyCar(new AICar(new Car())));
		water.move();
	}
}

优点
1)扩展对象功能,比继承灵活,不会导致类个数急剧增加
2)可以对一个对象进行多次装饰,创建出不同行为的组合,得到的功能更强大的对象。
3)具体构建类和具体装饰类可以独立变化,用户可以根据需要自己增加新的具体构建子类和具体装饰子类
缺点
1)产生很多小对象。大量小对象占据内存,一定程度上影响性能。
2)装饰模式易于出错,调试排查比较麻烦
IO流实现细节
1)抽象构件角色 InputStream,OutputStream,Reader,Writer
2)具体构件角色 FileInputStream,FileOutputStream
3)装饰器角色 FilterInputStream,FilterOutputStream 持有一个抽象构件的引用
4)具体装饰角色 BufferedInputStream,BufferedOutputStream 等
在这里插入图片描述

16.Apache IOUtils的使用_Apache FileUtils的使用

16.1IOUtils 与 FileUtils

**Commons IO 是 apache 的一个开源的工具包,封装了 IO 操作的相关类,使用 Commons IO 可以很方便的读写文件, **
FileUtils 中提供了许多设计文件操作的 已封装好的方 法。
IOUtils 则是提供了读写文件的方法 .

16.2IOUtils 工具类操作的相关方法

String IOUtils.toString(InputStream input)传入输入流对象 返回字符串

16.3FileUtils 工具类操作的相关方法

  1. String FileUtils.readFileToString(File file,String encoding)
  2. FileUtils.writeStringToFile(File file,String data,String encoding)读写文件
  3. FileUtils.copyFile(File srcFile,File destFile)复制文件
  4. )FileUtils.copyURLToFile(URL source,File destination)复制 url 对象到指定文件
public class TestIOUtils {
	public static void main(String[] args) throws FileNotFoundException, IOException {
		//读数据
		String str = IOUtils.toString(new FileInputStream("D:\\123.txt"));
		System.out.println(str);
		
		//写数据
		IOUtils.write(str, new FileOutputStream("D:\\456.txt"));
		
		//复制文件中的内容
		IOUtils.copy(new FileInputStream("D:\\123.txt"), new FileOutputStream("D:\\789,txt"));
	}
}
public class TestFileUtils {
	public static void main(String[] args) throws IOException {
		FileUtils.copyFile(new File("D:\\123.txt"),new File("D:\\101.txt"));
		
		URL url = new URL("https://www.baidu.com");
		FileUtils.copyURLToFile(url, new File("D:\\baidu.html"));
	}
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值