黑马程序员_【总结】_IO知识梳理1

IO知识梳理1


---------- android培训 java培训、期待与您交流! ---------- 

---------------------------------------------------------------------------------------------------------------------------------------------
1、字符流 Reade--Writer
2、字节流InputStream--OutputStream
3、4个顶层类都是抽象类。
由这4个类派生出的子类名称都是以其父类名作为子类的后缀。
3、操作纯文本--字符流     非纯文本如图片、视频--字节流
4、BufferedReader bufr =     //键盘录入  最常见的写法。 重点
new BufferedReader(new InputStreamReader(System.in));
5、读取文件,并写入一个新的文件。 通过缓冲区进行效率的提高。
写入时,一定要注意  换行--刷新--关闭  资源动作。
6、流操作最痛苦的就是,流对象有很多,不知道用那一个。
通过【三个明确】来完成。
1、明确  源和目的。
2、明确  操作的数据是否为纯文本。
3、当体系明确后,在明确要使用那个具体的对象。
7、装饰设计模式:构建一个新的类,把已有的对象传入进行功能的增强
一旦自己的方法出BUG,还可以使用原来的功能。
BufferedReader  等就是装饰类。
8、LineNumberReader 代行号的增强类。
setLineNumber() 写入行号  括号内为起始数字
getLIneNumber() 获取行号
9、转换流什么时候用,字符,字节之间的桥梁,通常涉及到字符编码转换时,需要用到转换流
-------------------------------------------------------
【1】
1、3个明确
						|-- Reader
			源:		读取	|-- InputStream
明确源和目的
			目的:	        写入    |-- Writer
						|-- OutputStream
----------------------------
					|--Reader
				是 	|--Writer
明确是否纯文本		
				否 	|--InputStream				
					|-- OutputStream
----------------------------
					内存	  |-- ByteArrayInputStream
					硬盘	 -|--FieReader
		 源设备			         -|--FileInputStream
					键盘	  |--System.in
明确设备
					内存 	|--ByteArrayOutputStream
		目的设备 		硬盘   -|-- FileWriter
					       -|-- FileOutputStream
					控制台	|-- System.out
----------------------------------------------------------------

2-1、转换流
InputStreamReader---OutputStreamWriter  
字节> 字符                                  字符>字节
2-2、缓冲区
BufferedReader--BufferedWriter
BufferedInputStream-BufferedOutputStream
2-3
LineNumberReader: 跟踪行号的缓冲字符输入流
1、getLineNumber()  获取行号
2、setLineNumber(int lineNumber)   设置当前行号。
2-4、 字节流里的 read、write
read 返回的值是int 说明存在类型提示,在数据的高位补0,放置出现-1的情况
write 输出的是byte,说明存在强制转型,就不会造成文件变大。
2-5、更改标准输入、输出设备
System.setIn();
System.setOut();

IOException--IO异常    捕获的CATCH异常,告诉操作者路径不对
NullPointerException 空指针异常 当流没有被创建而进行了关闭动作。 需要进行null判断
----------------------------------------------------------------
【2】
//COPY
class $3CopyTestByBuf{
	public static void main(String[] args)  {
		//创建出读取、写入流,以及读取、写入缓冲区。
		FileReader fr = null;
		FileWriter fw = null;
		BufferedReader brr =null;
		BufferedWriter brw =null;
		try{
			//指定读取、写入流并关联文件
			fr = new FileReader("Test8.java");
			fw =new FileWriter("D:\\Test8.java");
			//把需要优化的流放入相应的缓冲区,进行高效运作。
			brr = new BufferedReader(fr);
			brw = new BufferedWriter(fw);
			//通过读取整行,并写入的方式进行拷贝,注意【换行】和【刷新】
			String str = null;
			while((str=brr.readLine())!=null){
				//brw.write(str,0,str.length());//把读取的一行插入
				brw.write(str);//直接写入就可以了,因为有换行,上面一句复杂了
				brw.newLine();//换行动作
				brw.flush();//刷新动作
			}
		}
		catch(IOException e){
			System.out.println(e.toString());
		}
		finally{
			try{
				if(brr!=null)
					brr.close();	//【一定要关闭】	
			}
			catch(IOException e){
				System.out.println(e.toString());
			}
			finally{
				try{
					if(brw!=null)
						brw.close();//【一定要关闭】
				}
				catch(IOException e){
					System.out.println(e.toString());
				}
			}
		}
	}
}
读取文件,并写入一个新的文件。 通过缓冲区进行效率的提高。
1、写入时,一定要注意换行、刷新。  最后是关闭资源动作。
【3】
装饰模式
装饰设计模式的有优点,继承的区别。

模拟追溯Reader当时的创建
 
 我们设计出一个用于读取数据的类
 并设计出具体不同功能的子类
设计出缓冲技术,继承子类并对其进行增强
MyReader
	|--MyTextReader                //Test
		|--MyBurredTestReader
	|--MyMediaReader               //Media
		|--MyBurredMediaReader
	|--MyDataReader                 //Date
		|--MyBurredDateReader
这样就设计出一个体系,后来我们发现该体系臃肿,
发现缓冲技术是共性的,所以我们提炼出来:
class MyBufferedReader{
	MyBufferedReader(MyTextReader test){}
	MyBufferedReader(MyMediaReader media){}
}
可是该方法扩展性依旧不够:
找到其参数的共同类型,通过多态的形式,可以提高扩展性,
多态是要继续才有的。而共同类型就是 MyReader
所以:
class MyBufferedReader extends MyReader{
	Private MyReader r;
	MyBufferedReader(MyReader r){}
}
经过一步步的优化,我们原来设计的体系就发生了一些变化:
MyReader
	|--MyTextReader                //Test
	|--MyMediaReader               //Media
	|--MyDataReader                 //Date
	|--MyBufferedReader  (他里面没有东西,都是基于MyReader下其他类的东西并增强)
相对与原来的体系,更清晰了很多,
------------------------------------------------------------
这就是装饰设计体系模式对原有体系进行优化而产生的体系。
就是将原来臃肿的继承体系优化后变的更简单,更具有扩展性。

装饰模式比继承要灵活,避免了继承体系的臃肿
并降低了类与类之间的关系。(不用在必须继承)
装饰类因为是增强已有对象,具备 的功能和已有对象是相同的,只不过提供了,更强的功能,
所以装饰类和被装饰类,通常都属于一个体系中。


装饰设计模式把继承结构改成了组合结构。
---------------------------------------------------------------------------------

(什么时候用装饰设计模式呢,譬如你接收一个项目,有些功能是以前写的,你不可能改动呀,
那么写一个增强类,把原来的功能传递进来并增强,一旦自己的方法出BUG,还可以使用原来的功能。)


。。。。。。。。。。。。。。。。。。。。
装饰设计模式
当想要把已有的对象进行功能的增强时,
可以定义类,将已有对象传入,基于已有的功能,并提供加强功能
那么自定义的类称为装饰类。


装饰类,通常会通过构造方法接收被装饰的对象
并基于该被装饰的对象功能,提供更强的功能。
BufferedReader  等就是装饰类。

要增强类 和增强类, 都应该同属于一个类或者一个接口。是一个体系中的成员。
class Person{
	public void chifan(){
		System.out.println("吃饭");
	}
}
class SuperPerson {
	private Person p ;
	SuperPerson(Person p){//增强功能必须要先有原有功能。
		this.p = p;
	}
	public void superchifan(){//功能的增强。
		System.out.println("开胃酒");
		p.chifan();
		System.out.println("甜点");
	}
}
class ZhuangshiMoshi5{
	public static void main(String[] args) {
		Person p = new Person ();
		//p.chifan();
		//把要增强的功能放入增强类中。
		SuperPerson sp = new SuperPerson(p);
		sp.superchifan();
	}
}
代行号的增强类。
LineNumberReader  提供了 
setLineNumber() 写入行号  括号内为起始数字
		getLIneNumber() 获取行号

		FileReader fr = new FileReader("Test8.java");
		LineNumberReaderlnr = new LineNumberReader(fr);

		String line = null;
		lnr.setLineNumber(50);//【3】设置行号  会从51开始进行行号累计。
		while((line=lnr.readLine())!=null){
			//System.out.println(line);//【1】   成功读取
			System.out.println(lnr.getLineNumber()+"|"+line);//【2】加入行号
		}
【5】
复制一张图片。
思路
1、用字节流读取对象和图片关联
2、用字节流写入流对象创建一个图片文件,用于储存取到的图片数据。
3、通过循环读写,完成数据的存储。
4、关闭资源
class CopyPicTest9 {
	public static void main(String[] args) {
		copy();
	}
	public static void copy(){	
		FileOutputStream fos =null;
		FileInputStream fis =null;
		try{
			fos = new FileOutputStream("D:\\p.jpg");//写
			fis = new FileInputStream("E:\\p.jpg");//读
			byte [] by = new byte[1024];
			int len = 0;
			while((len=fis.read(by))!=-1){
				fos.write(by,0,len);
			}
		}
		catch(IOException e){
			System.out.println(e.toString());
		}
		finally{
			try{
				if(fis!=null)
					fis.close();
			}
			catch(IOException e){
				System.out.println(e.toString());
			}
			finally{
				try{
					if(fos!=null)
						fos.close();
				}
				catch(IOException e){
					System.out.println(e.toString());
				}
			}
		}
	}
}
图片,视频等非文本文件,需要使用字节流来操作。需要注意的是,字节流,
                        byte [] by = new byte[1024];
			int len = 0;
			while((len=fis.read(by))!=-1){
				fos.write(by,0,len);
			}
而字符流是:
                        //char [] ch = new char[1024];
			String str = null;
			while((str=brr.readLine())!=null){
				//brw.write(str,0,str.length());//把读取的一行插入
				brw.write(str);//直接写入就可以了,因为有换行,上面一句复杂了
				brw.newLine();//换行动作
				brw.flush();//刷新动作
			}
接收键盘录入:
InputStream in = System.in;
【6】
转换流
通过刚才的【ReadIn92】键盘录入一行的数据并打印其大写,发现,其实就是读一行数据的原理。
也就是readLine() 方法。 能不能直接使用readLine 方法来完成键盘录入的一行数据进行读取呢?


readLine  方法是【字符流】 BufferedReader 类中的方法
而键盘录入的read 方法是【字节流】InputStream 类中的方法


那么能不能把【字节流】转换为【字符流】,然后使用字符流的缓冲区的readLine方法呢?

这就是转换流。

既然有字节流转向字符流肯定就有字符流转向字节流。
我们输入的时候是字符,而存入硬盘的都是字节数据。
InputStreamReader
OutputStreamWriter
class  InputStreamReader93
{
	public static void main(String[] args) throws IOException
	{
		//1、创建字节流接收一个键盘录入
		//1-2、把字节流放入转换流,转换为字符流
		//1-3、把字符流进行缓冲技术提高效率

		//2-1、创建一个写入字节流,2-2并转换为写入字符流,2-3并放入缓冲区。
		//InputStream in = System.in;//【1】-1
		//InputStreamReader isr = new InputStreamReader(in);//【1】-2  转换流。
		//BufferedReader bufr = new BufferedReader(isr);//【1】-3
	
		//OutputStream os = System.out;//【2】-1
		//OutputStreamWriter osw = new OutputStreamWriter(os);//【2】-2 转换流
		//BufferedWriter bufw = new BufferedWriter(osw);//【2】-3     
		//【把1,2,进行简写】
		BufferedReader bufr =//键盘录入  最常见的写法。 重点
			new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bufw=
			new BufferedWriter(new OutputStreamWriter(System.out));
		//【4】:
		String line = null;
		while((line = bufr.readLine())!=null){  //  BufferedReader 缓冲区方法。
		if("over".equals(line))//设置一个结束标记
				break;
			//System.out.println(line.toUpperCase());
			bufw.write(line.toUpperCase());
			>bufw.newLine();//缓冲区方法。换行
			bufw.flush();//刷新  写入数据一定不要忘记两大步奏---刷新-关闭。。
		}
		bufr.close();
		bufw.close();
	}
}
InputStreamReader---OutputStreamWriter  把流进行转换
【7】
【流操作的基本规律】:
最痛苦的就是,流对象有很多,不知道用那一个。
通过【三个明确】来完成。

1、明确  源和目的。
   源  : 输入流  InputStream  Reader
目的: 输出流  OutputStream Writer
2、明确  操作的数据是否为纯文本。
是:  字符流
否:  字节流
3、当体系明确后,在明确要使用那个具体的对象。
通过设备来区分:
源设备  : 内存、硬盘、键盘。
目的设备: 内存、硬盘、控制台。
-------
根据以上3点,写出3个需求。
1、将一个文本文件中的数据存储到另一个文件中。复制文件。
分析:
1、源: 因为是源,所以使用读取流:InputStream  Reader
是不是操作文本文件
是!这时候就选择:Reader
这时候体系就明确了。
接下来明确要是用体系中的那个对象。
明确设备:硬盘 。上的一个文件。
Reader 体系中,可以操作文件的对象是: FileReader
是否需要提高效率: 是!  加入Reader体系中的缓冲区。

FileReader fr = new FileReader("a.txt");
BufferedReader bufr = new BufferedReader(fr);

2、目的: OutputStream Writer
是否为纯文本
是!Writer
设备:硬盘,一个文件
Writer 体系中,可以操作文件的对象是: FileWriter

是否需要提高效率: 是!  加入Writer体系中的缓冲区。

FileWriter fw = new FileWriter("a.txt");
BufferedWriter bufw =new BufferedWriter(fw);
-----------------------------
练习: 将一个图片文件中数据存储到另一个文件中,复制文件,要求同上,自己分析出3个明确。
分析:
  1 源  :  源都是读取流,InputStream  Reader
而图片文件不是纯文本文件所以用InputStream 
而目设备是电脑中一文件。
而在InputStream中操作文件的对象是 FileInputStream
所以:  然后考虑是否需要缓冲技术:
FileInputStream in = new FileInputStream()
  2 目的: OutputStream Writer
操作的不是纯文本文件  OutputStream 
而目设备是电脑中一文件。
而在OutputStream中操作文件的对象是 FileOutputStream
所以:  然后考虑是否需要缓冲技术:
FileOutputStream out = new  FileOutputStream();
---------------------------------------------------------------
2、需求,将键盘录入的数据存到一个文件当中
分析:1、源:InputStream  Reader
是不是纯文本?  是!   选择 Reader
设备是 键盘  对应的对象是: System.in
问题来了,Reader是字符流,System.in是字节流对象
为了操作键盘的文本数据方便,转为字符流按照字符串操作是最方便的
所以明确了 Reader 那么将System.in 转换成Reader
用到Reader 中的转换流,InputStreamReader
InputStreamReader isr = new InputStreamReader(System.in);
是否需要缓冲技术进行效率的提高?
BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in));

2、目的地:  OutputStream Writer
是不是纯文本?  是 ! Writer
设备是:硬盘 一个文件   所以操作对象是: FileWriter
FileWriter fw = new FileWriter();
需要缓冲技术吗,
BufferedWriter bufw = new BufferedWriter()
------------
【7-2】【重点】扩展:想要把录入的数据按照指定编码表,将数据存储到文件中
2、目的地:  OutputStream Writer
是不是纯文本?  是 ! Writer
设备是:硬盘 一个文件   所以操作对象是: FileWriter
但是FileWriter 使用的是默认编码表:GBK
但是存储时,需要加入指定编码表 utf-8 而指定的编码变 只有转换流可以指定
所以要使用的对象是 OutputStreamWriter.
而该转换流对象要接收一个字节输出流,而且还可以操作的文件的字节输出流:FileOutputSteam
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputSteam("a.txt"),"UTF_8");
【指定编码表】
需要高效吗?
BuffreedWriter bufw =new BuffreedWriter(osw);>>>>>写成一句话:
BuffreedWriter bufw =
new BuffreedWriter(new OutputStreamWriter(new FileOutputSteam("a.txt"),"UTF_8"));
记住: 转换流什么时候用,字符,字节之间的桥梁,通常涉及到字符编码转换时, 需要用到转换流
练习:将一个文本数据打印到控制台上,按照上列要求,写出3个明确。
分析 1 、 源,InputStream Reader
是不是纯文本? 是   所以  Reader
设备:硬盘,一个文件   所以FileReader 
是否需要高效
BufferedReader bufr = new BufferedReader(new FIleReader("a.txt"));
2、目的, OutputStream Writer
是不是纯文本? 是!  Writer
设备: 控制台     对应的对象是:System.out
Writer 字符流,而System.out 是字节流。  那么需要进行转换
OutputStreamWriter osw = new OutputStreamWriter(System.out);
是否需要提高效率
BufferedWriter bufw = new BufferedWriter(osw);
------------------------------------------------------
class TransStreamDemo94{
	public static void main(String[] args) throws IOException{
		//show_1();
		show_2();
	}
	public static void show_1() throws IOException{
		//  了解下(不常用。):  System.setIn  和System.setOut
		//	System.setIn(new FileInputStream("Test8.java"));
		//	System.setOut(new PrintStream("zzz.txt"));

		//【】括号内对应最定上需求。
		BufferedReader bufr =   //键盘录入
			new BufferedReader(new InputStreamReader(System.in));//【1】【2】
			//new BufferedReader(new InputStreamReader(new FileInputStream("E:\\123.txt")));//【3】
		BufferedWriter bufw =
			new BufferedWriter(new OutputStreamWriter(new FileOutputStream("D:\\12345.txt"),"UTF-8"));//【2】
			//new BufferedWriter(new OutputStreamWriter(System.out));//【1】【3】

		String line = null;
		while((line=bufr.readLine())!=null){
			if("over".equals(line))
				break;
			bufw.write(line.toUpperCase());
			bufw.newLine();
			bufw.flush();
		}
		bufr.close();
		bufw.close();
	}
	//练习:将一个文本数据打印到控制台上,按照上列要求,写出3个明确。分析在上。
	public static void show_2() throws IOException{
		BufferedReader bufr = new BufferedReader(new FileReader("Test.txt"));
		BufferedWriter bufw =
			new BufferedWriter(new OutputStreamWriter(System.out));
		String str = null;
		while((str=bufr.readLine())!=null){
			bufw.write(str);
			bufw.newLine();
			bufw.flush();
		}
		bufr.close();
		bufw.close();
	}
}
通过键盘写入3个文件,一个是不指定编码变,一个指定GBK 一个指定UTF-8
后比较3个文件发现,同样输入“你好” 的情况下三个文件,前2者都是6个字节,后者8个字节
字符编码后面在具体温习。




---------------------------------------------------------------------------------------------------------------------------------------------
---------- android培训、 java培训、期待与您交流!----------


----------------------------------------------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值