IO流缓冲流等高级流

IO流缓冲流等高级流

回顾
1 File类 表示硬盘中一个文件或文件夹(目录)
    文件:  
    	//1.1创建对象
        File file=new File("d:\\123.txt");
        //1.2判断文件是否存在
        if(!file.exists()){
          	file.createNewFile();
        }
        //1.3删除
        file.delete();
        file.deleteOnExit();//退出jvm,删除文件
        //1.4可执行、可读、可写
        file.canExecute();
        file.canRead();
        file.canWrite();
        //1.5获取
        file.getAbsoulatePath();
        file.getPath();
        file.getName();
        file.getParent();
        file.lastModified();//修改时间
        //1.6判断
        file.isFile();
        file.isHidden();
        file.renameTo();//重命名
    文件夹 :
     	//2.1创建文件夹
     	File dir=new File("d:\\aaa\\bbb");
     	//2.2判断是否存在
     	if(!dir.exists()){
           dir.mkdir();//一级目录
           dir.mkdirs();//多级目录
     	}
     	//2.3删除
     	dir.delete();
     	dir.deleteOnExit();
     	//2.4获取
     	 dir.getAbsoulatePath();
        dir.getPath();
        dir.getName();
        dir.getParent();
        //2.5判断
        dir.isDirectory();
        dir.isHidden();
        dir.renameTo();
        //2.6列出来当前目录下的文件和文件夹
        dir.list();//String[]
        dir.listFiles();//File[]
        dir.list(FileNameFilter);
        File.listRoots();//返回所有的盘符
        
  2递归遍历文件夹中所有的文件和子文件
  3递归删除文件夹
  4 IO  (Input Output)
  流:是数据传输的通道。
  输入: 从外部存储到内存(java程序)(读取)
  输出: 从内存到外部存储 (写入)
  IO分类 :
     1  按照流向  输入流和输出流
     2  按照字节个数  字节流和字符流
     3  按照功能   节点流和处理流
    
  5  字节流 
  	 InputStream  ----> FileInputStream
     OutputStream  ---->FileOutputStream
     
  6 字符流
     Reader  ----->InputStreamReader---->FileReader
     Writer ----->OutputStreamWriter ---->FileWriter
  7 转换流 
  	InputStreamReader:字节流通向字符流的桥梁,指定编码
  	OutputStreamWriter:字符流通向字节流的桥梁,指定编码
     
  8 复制文件
  	使用字节流复制
    
今天内容
1.缓冲流
	2.1 BufferedInputStream类的使用
	2.2 BufferedOutputStream类的使用
	2.3 BufferedReader类的使用
	2.4 BufferedWriter类的使用
2.内存流
3.标准输入输出流
4.对象流
5.RandomAccessFile类
6.Properties类
7.装饰者设计模式
教学目标
1.掌握缓冲、内存流的使用
2.了解标准输入输出流的使用
3.掌握对象流的使用
4.了解RandomAccessFile类的使用
5.掌握Properties的使用
6.了解装饰者设计模式
第一节 缓冲流
作用:主要是为了增强基础流的功能而存在的,提高了流的工作效率【读写效率】

注意:如果使用记事本创建的文件,文件是utf-8或者unicode编码,文件的前面有一个BOM(Byte Order Mark)头,BOM作用指定文件使用的编码类型。GBK编码没有添加bom头。
utf-8:EF BB BF 
unicode 小端: FF FE     66 00
unicode 大端 :FE FF    00 66
1.1 BufferedInputStream类
public class BufferedInputStreamDemo {
	public static void main(String[] args) throws IOException {
		//实例化一个File对象
		File file = new File("file/test22.txt");
		
		//实例化一个缓冲字节输入流的对象
		BufferedInputStream input = new BufferedInputStream(new FileInputStream(file));
		
		/*
		//读取
		byte[] arr = new byte[1024];
		int len = 0;
		while((len = input.read(arr)) != -1) {
			String string = new String(arr, 0, len);
		}
		*/
		
		byte[] arr = new byte[4];
		int len = input.read(arr);
		String string = new String(arr, 0, len);
		System.out.println(string);
		
		input.mark(66);
		
		len = input.read(arr);
		string = new String(arr, 0, len);
		System.out.println(string);

		// 实现了效果:覆水可收
		input.reset();

		len = input.read(arr);
		string = new String(arr, 0, len);
		System.out.println(string);

		input.close();
	}
}
1.2 BufferedOutputStream类
public class BufferedOutputStreamDemo {
	public static void main(String[] args) throws IOException {
		//实例化FIle对象
		File file = new File("test33.txt");
		
		//实例化换种字节输出流 
		BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(file));
		
		//写
		output.write("你好的halle".getBytes());
		
		//刷新
		output.flush();
		
		//关闭
		output.close();
	}
}
1.3 BufferedReader类
public class BufferedReaderDemo {

	public static void main(String[] args) throws IOException {
		//实例化FIle对象
		File file = new File("test33.txt");
		
		//实例化缓冲字符流的对象
		BufferedReader reader = new BufferedReader(new FileReader(file));
		
		//方式一:read循环读取
		/*
		//读取
		char[] arr = new char[8];
		int len = 0;
	
		while((len = reader.read(arr)) != -1) {
			String string = new String(arr, 0, len);
		}
		*/
		
		//方式二:readLine循环读取
		/*
		String result1 = reader.readLine();
		System.out.println(result1);
		
		String result2 = reader.readLine();
		System.out.println(result2);
		*/
		String result = "";
		while((result = reader.readLine()) != null) {
			System.out.println("第一行:" + result);
		}
		
		reader.close();
	}
}
1.4 BufferedWriter类
public class BufferedWriterDemo {
	public static void main(String[] args) throws IOException {
		// 实例化FIle对象
		File file = new File("test33.txt");
		
		//实例化缓冲字符输出流
		BufferedWriter writer = new BufferedWriter(new FileWriter(file,true));

		// 写
		writer.write("今天天气还可以");

		// 作用:主要就是为了换行
		writer.newLine();

		// 刷新
		writer.flush();
		
		//关闭
		writer.close();
	}
}
第二节 内存流
输入和输出都是从文件中来的,当然,也可将输出输入的位置设置在内存上,这就需要ByteArrayInputStream和ByteArrayOutputStream

	ByteArrayInputStream:将内容写入到内存中,是Inputstream的子类
	ByteArrayOutputStream:将内存中数据输出,是OutputStream的子类
	此时的操作应该以内存为操作点	

案例:完成一个字母大小写转换的程序

public class TextDemo02 {
	public static void main(String[] args) throws IOException {
		//定义一个字符串,全部由大写字母组成
		String string = "HELLOWORLD";
		
		//内存输入流
		//向内存中输出内容,注意:跟文件读取不一样,不设置文件路径
		ByteArrayInputStream bis  = new ByteArrayInputStream(string.getBytes());
		//内存输出流
		//准备从内存中读取内容,注意:跟文件读取不一样,不设置文件路径
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		
		int temp = 0;
		//read()方法每次只读取一个字符
		while((temp = bis.read()) != -1) {
			//将读取的数字转为字符
			char c = (char)temp;
			//将字符变为大写
			bos.write(Character.toLowerCase(c));
		}
		//循环结束之后,所有的数据都在ByteArrayOutputStream中
		//取出内容,将缓冲区内容转换为字符串
		String newString = bos.toString();
		
		//关闭流
		bis.close();
		bos.close();
		System.out.println(newString);
	}
}
实际上以上操作很好体现了对象的多态。通过实例化其子类不同,完成的功能也不同,也就相当于输出的位置不同,如果是输出文件,则使用FileXxxx类。如果是内存,则使用ByteArrayXxx。

	总结:	
	 a.内存操作流的操作对象,一定是以内存为主准,不要以硬盘为准。
	 b.实际上此时可以通过向上转型的关系,为OutputStream或InputStream.
	 c.内存输出流在日后的开发中也是经常使用到,所以一定要重点掌握
第三节 标准输入输出流
Java的标准输入/输出分别通过System.in和System.out实现,默认情况下分别代表是键盘和显示器
public class PrintStreamDemo {
	public static void main(String[] args) throws FileNotFoundException {
		//System.out.println("hello world");
		//创建打印流的对象
		//注意:默认打印到控制台,但是,如果采用setOut方法进行重定向之后,将输出到指定的文件中
		PrintStream print = new PrintStream(new FileOutputStream(new File("test33.txt")));
		/*
		 * static void setErr(PrintStream err) 
          	重新分配“标准”错误输出流。 
		static void setIn(InputStream in) 
          	重新分配“标准”输入流。 
		static void setOut(PrintStream out) 
          	重新分配“标准”输出流。 
		 * */
		//将标准输出重定向到print的输出流
		System.setOut(print);
		
		System.out.println("hello world");
	}
}
public class InputStreamDemo {
	public static void main(String[] args) throws FileNotFoundException {
		FileInputStream inputStream = new FileInputStream(new File("test33.txt"));
		
		//setIn
		System.setIn(inputStream);
		
		//System.out.println("请输入内容:");
		
		//默认情况下是从控制台进行获取内容
		//但是如果使用setIn方法设置了重定向之后,将从指定文件中获取内容
		Scanner sc = new Scanner(System.in);
		
		String string = sc.next();
		
		System.out.println(string);
	}
}
第四节 对象流
流中流动的数据是对象
	将一个对象写入到本地文件中,被称为对象的序列化
	将一个本地文本中的对象读取出来,被称为对象的反序列化
使用对象流
	ObjectInputStream: 对象输出流
	ObjectOutputStream:对象输入流

	注意:
		一个对象流只能操作一个对象,如果试图采用一个对象流操作多个对象的话,会出现EOFException【文件意外达到了文件末尾】

		如果向将多个对象序列化到本地,可以借助于集合,【思路:将多个对象添加到集合中,将集合的对象写入到本地文件中,再次读出来,获取到的仍然是集合对象,遍历集合】
		
对象中那些字段可以不序列化:
	1 transient 修饰的字段
	2 静态的字段
在要序列化类中添加字段,保证序列化和反序列化是同一个类	
private static final long serialVersionUID = 100L;
public class ObjectStreamDemo {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//objectOutputStreamUsage();
		objectInputStreamUsage();
	}

	// 写:将对象进行序列化
	public static void objectOutputStreamUsage() {
		//1.实例化一个Person的对象
		Person person =  new Person("张三", 10, 'B');
		
		//2.实例化一个对象输出流的对象
		ObjectOutputStream output = null;
		try {
			output = new ObjectOutputStream(new FileOutputStream(new File("file/person.txt")));
		
			//3.将对象写入到流中
			output.writeObject(person);
			
			//4.刷新
			output.flush();
		
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		finally {
			try {
				output.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	// 读:反序列化
	public static void objectInputStreamUsage() {
		//1.实例化对象输入流的对象
		try {
			ObjectInputStream input = new ObjectInputStream(new FileInputStream(new File("file/person.txt")));
		
			//2.读取
			Object object = input.readObject();
			
			//3.对象的向下转型
			if(object instanceof Person) {
				Person p = (Person)object;
				System.out.println(p);
			}
		
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}	
注意:在使用对象流的时候,用于初始化对象流的参数只能是字节流(将对象转换为二进制的形式,然后再把二进制写入文件)
第五节 RandomAccessFile类
RandomAccessFile是用来访问那些保存数据记录的文件的,你就可以用seek( )方法来访问记录,并进行读写了。这些记录的大小不必相同;但是其大小和位置必须是可知的。但是该类仅限于操作文件。

案例一:RandomAccessFile类的应用

public class TextDemo01 {
	public static void main(String[] args) throws Exception {
		RandomAccessFile file = new RandomAccessFile("file.txt", "rw");
		// 以下向file文件中写数据
		file.writeInt(20);// 占4个字节
		file.writeDouble(8.236598);// 占8个字节
		//这个长度写在当前文件指针的前两个字节处,可用readShort()读取
		file.writeUTF("这是一个UTF字符串");
		file.writeBoolean(true);// 占1个字节
		file.writeShort(395);// 占2个字节
		file.writeLong(2325451l);// 占8个字节
		file.writeUTF("又是一个UTF字符串");
		file.writeFloat(35.5f);// 占4个字节
		file.writeChar('a');// 占2个字节
		//把文件指针位置设置到文件起始处
		file.seek(0);

		// 以下从file文件中读数据,要注意文件指针的位置
		System.out.println("——————从file文件指定位置读数据——————");
		System.out.println(file.readInt());
		System.out.println(file.readDouble());
		System.out.println(file.readUTF());
		
		//将文件指针跳过3个字节,本例中即跳过了一个boolean值和short值。
		file.skipBytes(3);
		System.out.println(file.readLong());
		
		//跳过文件中“又是一个UTF字符串”所占字节
		//注意readShort()方法会移动文件指针,所以不用写2。
		file.skipBytes(file.readShort()); 
		System.out.println(file.readFloat());

		// 以下演示文件复制操作
		System.out.println("——————文件复制(从file到fileCopy)——————");
		file.seek(0);
		RandomAccessFile fileCopy = new RandomAccessFile("fileCopy.txt", "rw");
		int len = (int) file.length();// 取得文件长度(字节数)
		byte[] b = new byte[len];
		//全部读取
		file.readFully(b);
		fileCopy.write(b);
		System.out.println("复制完成!");
	}
}
第六节 Properties类
是Map接口的一个实现类,并且是Hashtable的子类
	Properties文件中元素也是以键值对的形式存在的
Properties特点:
1 存储属性名和属性值
2 属性名和属性值都是字符串
3 和流有关系
4 没有泛型
	
public class PropertiesDemo {
	public static void main(String[] args) {
		//1.实例化一个Properties的对象
		Properties pro = new Properties();
		System.out.println(pro);
		
		//2.把文件userlist.properties中的键值对同步到集合中
		//实质:读取
		/**
		 *  void load(InputStream inStream) 
          	从输入流中读取属性列表(键和元素对)。 
		 */
		try {
			pro.load(new BufferedInputStream(new FileInputStream(new File("file/userlist.properties"))));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		System.out.println(pro);
		
		//3.向集合中添加一对键值对
		/*
		 *  Object setProperty(String key, String value) 
          	调用 Hashtable 的方法 put。 
		 * */
		pro.setProperty("address", "china");
		
		System.out.println(pro);
		
		try {
			//4.store
			//实质:写入
			//comments:工作日志
			pro.store(new BufferedOutputStream(new FileOutputStream(new File("file/userlist.properties"))), "add a pair of key and value");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
第七节 装饰者设计模式
 	装饰者模式是向一个现有的对象添加新的功能,同时又不改变其结构。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
 	应用场景:需要扩展、增强一个类的功能,或给一个类添加附加职责。
	扩展类的功能有两种实现方法:
	1 继承重写
	  优点:简单
	  缺点:1 类体系太庞大 2 耦合性太高  3子类继承不需要的方法
	2 装饰者模式
      缺点:多层装饰比较复杂
      优点:耦合性低,提高重用性,符合合成(聚合)复用原则
      
 java面向对象的设计原则 7大原则
 开(总则) 开闭原则, 对扩展开放,对修改关闭
 口 :接口隔离原则,使用接口隔离,降低程序耦合性
 合 :合成聚合复用,不用继承,使用组合(强拥有关联)、聚合(弱拥有关联)   学校类  (List<Student>)
 里 : 里氏替换原则,多态  父类能使用的地方,都可以替换成子类  Animal animal=new Dog();
 最 :最少知道原则(迪米特法则),一个类不要知道太多其他的类
 单: 单一职责原则,一个类只负责一类功能,如果一个类功能太多,需要拆分。
 依: 依赖倒置原则,不依赖具体的类,依赖接口或抽象类。降低程序耦合性

代码实现:

/**
 * 抽象人类
 * @author wgy
 *
 */
public abstract class AbstractPerson {
	public abstract void eat();
}
/**
*子类1
*/
public class Student extends AbstractPerson {
	String name;
  	String school;
	
	public void eat() {
		System.out.println(name+"正在吃东西.........");
	}
	
}
package com.qf.day18_6;
/**
 * 子类2
 * @author wgy
 *
 */
public class Teacher extends AbstractPerson{

	String name;
  	int workyear;
	@Override
	public void eat() {
		System.out.println(name+"吃......");
		
	}

}
package com.qf.day18_6;

import java.io.BufferedInputStream;

/**
 * 增强Person
 * @author wgy
 *
 */
public class StrongPerson extends AbstractPerson {
	//使用person创建一个变量
	AbstractPerson p;

	public StrongPerson(AbstractPerson p) {
		this.p = p;
	}
	
	public void eat() {
		p.eat();
		System.out.println("抽一口");
		System.out.println("眯一会");
		System.out.println("写会java代码");
	}
	
}
//测试类
package com.qf.day18_6;

public class Test {
	public static void main(String[] args) {
		Student benwei=new Student();
		benwei.name="本伟";
		
		Teacher zhengshuai=new Teacher();
		zhengshuai.name="郑帅";
		
		StrongPerson strongPerson=new StrongPerson(benwei);
		StrongPerson strongPerson2=new StrongPerson(zhengshuai);
		
		strongPerson.eat();
		strongPerson2.eat();
			
	}
}

扩展案例:

1 抽象类 ReadFile -->read抽象方法
2 定义一些子类
    ReadTextFile 读取文本文件
    ReadMusicFile 读取音乐文件
    ReadVideoFile 读取视频文件
3 要求:提高三个类的功能 带缓冲    
   3.1继承
     BufferedReadTextFile继承ReadTextFile 重写 read方法
     BufferedReadMusicFile继承ReadMusicFile 重写 read
     BufferedReadVideoFile继承ReadVideoFile 重写 read
     缺点:1 类体系太庞大 2 耦合性太高
   3.2装饰者设计模式 :采用组合的关系
     BufferedReadFile{
         private ReadFile readFile;
         public BufferedReadFile(ReadFile readFile){
           this.readFile=readFile;
         }
         public void read(){
           ///
         }
     }
总结
1 缓冲流
	BufferedInputStream
	BufferedOutputStream
	BufferedReader  readLine();
	BufferedWriter  newLine();
2 内存流
	ByteArrayInputStream
	ByteArrayOutputStream
3 标准输入输出流
	System.in
	System.out 
	PrintStream打印流
4 对象流
	ObjectInputStream
	ObjectOutputStream
	序列化
	反序列化
5 RandomAccessFile类
6 Properties集合
7 装饰者设计模式
默写
1.使用转换流实现文件内容的拷贝

2.使用字符缓冲流实现文件内容的拷贝
作业
1.在电脑中盘下创建一个文件为HelloWorld.txt文件,判断他是文件还是目录,在创建一个目录FileTest,之后将HelloWorld.txt移动到FileText目录下去
2.在程序中写一个"HelloJavaWorld你好世界"输出到操作系统文件Hello.txt文件中
3.从磁盘读取一个文件到内存中,再打印到控制台
4.统计一个含有英文单词的文本文件的单词个数
5.从磁盘读取一个文件到内存中,再打印到控制台
6.实现将一个文件夹中的一张图片拷贝到另外一个文件夹下
7.将上课关于不同的流实现拷贝的案例敲熟练
8.定义一个类Student,定义属性:学号、姓名和成绩,方法:show(显示个人信息)

	实例化几个Student对象,将这几个对象保存到student.txt文件中
	然后再将文件中的内容读取出来并且调用show方法

9.从控制台输入一个字符串,统计其中一个字符出现的次数
10.理解装饰者设计模式,并实现类似课堂案例的案例

作业答案关注 +私信哦

面试题
1.BufferedReader属于哪种流,它主要是用来做什么的,它里面有那些经典的方法
2.怎么样把输出字节流转换成输出字符流,说出它的步骤
3.流一般需要不需要关闭,如果关闭的话在用什么方法,一般要在那个代码块里面关闭比较好,处理流是怎么关闭的,如果有多个流互相调用传入是怎么关闭的?
4.什么叫对象序列化,什么是反序列化,实现对象序列化需要做哪些工作
5.在实现序列化接口是时候一般要生成一个serialVersionUID字段,它叫做什么,一般有什么用
6.什么是内存流?有什么作用
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值