--------------------- android培训、java培训、java学习型技术博客、期待与您交流! -------------------
1 字节流
两个基类?
操作图片数据用什么流?
字节流的写入操作数组类型是什么?
字节流写入有什么特点?和字符流有什么区别?
字符流走的也是字节,但是会把字节存储起来,并进行查表。底层用还是字节流的缓冲区。直接使用字节流的话,因为单位是一个字节,所以一个一个读和写,不需要刷新。直接可以写入。但是关闭资源的close()方法一定要写上。
字符串如何转换成字节?字节如何转换成字符?
字节流读取的2个方式?
Available()是什么方法?怎么用?
返回对象中字节的个数。回车代表两个字符。直接被对象调用即可
import java.io.*;
class FileStream
{
public static void main(String[] args) throws IOException
{
//writeFile();
//readeFile_1();
//readeFile_2();
readeFile_3();
}
public static void readeFile_3()throws IOException
{
FileInputStream fis = newFileInputStream("fos.txt");
//int num = fis.available();//可以得知文件的具体字节数
byte[] buf = new byte [fis.available()];//定义一个刚刚好的缓冲区,不用再循环了。Available()返回对象中字节的个数。回车代表两个字符
//这个方法的好处就可以读取刚刚好的数组。但是慎用,如果一个电影1个g大小,用这个会把内存占满的。
fis.read(buf);
System.out.println(new String(buf);
fis.close();
}
public static void readeFile_2()throws IOException
{//另一种方式读取,通过建立字节数组
FileInputStream fis = newFileInputStream("fos.txt");
byte[] buf = new byte [1024];//数组
int len = 0;
while ((len=fis.read(buf))!=-1)//read(byte[] b) read的构造函数可以读取一个数组。
{
System.out.println(newString(buf,0,len));//String(byte[] bytes, int offset, int length) 通过使用平台的默认字符集解码指定的 byte 子数组,构造一个新的 String。这个是构造函数,输出buf数组中从0开始的第len个元素,以字符串的形式输出
}
fis.close();
}
public static void readeFile_1()throws IOException//建立一个方法
{
FileInputStream fis = newFileInputStream("fos.txt");//建立一个字节流对象fis
int ch = 0;
while ((ch=fis.read())!=-1)//当读取不为-1时,继续执行下面的操作
{
System.out.println((char)ch);//将ch转换成char型输出
}
fis.close();
}
public static void writeFile()throws IOException
{
FileOutputStream fos = newFileOutputStream("fos.txt");
fos.write("abcde".getBytes());//getBytes()函数的作用是将字符流转换成字符写入到字节流中。
//字节流不需要刷新,因为字节操作是最小的操作,直接可以进去写入操作字符流操作有点是以2个字节为一个字符的,所以需要刷新。
fos.close();//虽然不用刷新,但仍然要执行这个操作,这样可以关闭流节省资源
}
}
拷贝图片
思路:
1,用字节读取流对象和图片关联。
2,用字节写入流对象创建一个图片文件。用于存储获取到的图片数据。
3,通过循环读写,完成数据的存储。
4,关闭资源。
import java.io.*;
class CopyPic
{
public static void main(String[] args)
{//复制图片,用字符流是可以复制的,但是复制完的图片有可能打不开,因为字符流读完一段数据就会对照数码表,复制后文件有可能打不开
FileOutputStream fos = null;//建立2个字节流文件,
FileInputStream fis = null;
try
{
fos = new FileOutputStream("c:\\2.jpg");//写入文件是2.jpg
fis = new FileInputStream("c:\\1.jpg");//读取的文件是1
byte[] buf =new byte[1024];//数组
int len = 0;
while ((len=fis.read(buf))!=-1)
{
fos.write(buf,0,len);//进行写入
}
}
catch (IOException e)
{
throw new RuntimeException("复制失败");//如果上面的代码异常,就抛出复制失败
}
finally
{
try
{
if(fis!=null)
fis.close();
}
catch (IOException e)
{
throw new RuntimeException("读取失败");
}
try
{
if(fos!=null)
fos.close();
}
catch (IOException e)
{
throw new RuntimeException("写入失败");
}
}
}
}
拷贝MP3
import java.io.*;
class CopyMp3
{
public static void main(String[] args) throws IOException
{
long start =System.currentTimeMillis();
long end =System.currentTimeMillis();
System.out.println("时间:"+(end-start)+"毫秒");//调用currentTimeMillis()函数计算使用多少时间
copy_1();
}
public static void copy_1()throws IOException
{
BufferedInputStream bufis = new BufferedInputStream(newFileInputStream("c:\\1.mp3"));
BufferedOutputStream bufos = new BufferedOutputStream(newFileOutputStream("c:\\2.mp3"));
int len = 0;
while ((len=bufis.read())!=-1)
{
bufos.write(len);//进行写入
}
bufis.close();
bufos.close();
}
}
read(),write()的特点
自定义字节流缓冲区的代码?
为什么read()方法的返回值是int型?
如何读取键盘录入?
字符流转换字节流如何输入?
字节流转换字符流呢?
字节缓冲区读取的原理:
首先缓冲区定义了一个字节数组,然后从文件中抓了一堆数据,向数组里面存入,存满后,就读取,每读取一个字节,数组指针就减一。取完后数组指针指向0角标,再抓数据,从0角标开始继续存入。
自定义字节缓冲区会发现,read()方法第一个数值返回的就是-1。原因是读前八个字节如果都是1,那么返回成int型就都是-1.所以没法读取。如果想避免这种情况,就要转换int型的时候,前面3个八位补0,这样通过&255,就可以实现自定义字节流。
import java.io.*;
class MyBufferedInputStream//建立一个类,与BufferedInputStream功能一样。
{
private InputStream in;
private byte[] buf=new byte[1024*4];//建立数组
private int pos = 0,count=0;
MyBufferedInputStream(InputStream in)
{
this.in=in;
}
public int myRead()throws IOException
{//通过in对象读取硬盘上的数据,并存储到buf中
if(count == 0)
{
count = in.read(buf);//count值为读取buf后的int值,
if (count<0)//如果小于零,则返回-1,结束read函数
return -1;
pos=0;//每次count为零的时候。pos其实为1024*4-1,所以这条语句初始化pos
byte b = buf[pos];//将buf[]中元素赋值给b
count--;//自减函数count
pos++;//自加函数pos
return b&255;//与上255,使每个8为字节前面的24个都为0,避免有-1字节的出现
}
else if (count >0)//如果大于零
{
byte b = buf[pos];//就执行循环,把值赋给b
count--;
pos++;
return b&0xff;//统一将值与255。这个就是BufferedInputStream中的原理。read()方法返回的必须是int值,在做转换, 而write()写入的时候会自动转换回来
}
return -1;
}
public void myClose()throws IOException
{
in.close();
}
}
怎么将键盘录入的数据存储到一个文件中?
读取键盘录入。
System.out:对应的是标准输出设备,控制台。
System.in:对应的标准输入设备:键盘。
import java.io.*;
class ReadIn
{
public static void main(String[] args) throws IOException
{
InputStream in = System.in;//System.in对应的是输入设备。建立一个字符输入流对象in,用来接收键盘输入的字节
StringBuilder sb = new StringBuilder();//建立字符串数组
while (true)
{
int ch = in.read();//用ch判断read返回值
if (ch==13)//当为13,就是\r的时候,继续向下执行
continue;
if(ch == 10)//当为10,就是\n的时候
{
String s= sb.toString();//将sb转换为字符串形式返回给s
if("over".equals(s))//如果s的内容是字符串over
break;//那么终止循环。
System.out.println(s.toUpperCase());//不是over,那么就输出s的大写形式
sb.delete(0.sb.length());//如果不执行这个命令,每次输入的都会叠加。这条代码的作用就是每次输出后清空sb的内容。用delete。(集合才用clear())
}
else
sb.append((char)ch);//否则将ch转换成字节形式加入到sb中
}
/*
int ch = 0;
while ((ch=in.read())!=-1)
{
System.out.println(ch);
}
in.close();
int by = in.read();//用int型by值读取第一个字节,并把值赋给by
int by1 = in.read();
int by2 = in.read();
System.out.println(by);//打印by
System.out.println(by1);
System.out.println(by2);//输入a,输出结果是97 13 10,因为a对应的是字节编码表97,而\r\n分别对应13和10
*/
}
}
转换流的特点:
字符流:
FileReader
FileWriter。
BufferedReader
BufferedWriter
字节流:
FileInputStream
FileOutputStream
BufferedInputStream
BufferedOutputStream
通过刚才的键盘录入一行数据并打印其大写,发现其实就是读一行数据的原理。也就是readLine方法。能不能直接使用readLine方法来完成键盘录入的一行数据的读取呢?
readLine方法是字符流BufferedReader类中的方法。
而键盘录入的read方法是字节流InputStream的方法。
那么能不能将字节流转成字符流在使用字符流缓冲去的readLine方法呢?
import java.io.*;
class TransStreamDemo
{
public static void main(String[] args) throws IOException
{
//InputStream in = System.in;
//InputStreamReader isr = new InputStreamReader(in);//建立InputStreamReader对象 isr,将输入流in转换成字符流对象
//BufferedReader bufr = new BufferedReader(isr);//建立缓冲区
//上面三句话可以变成一句话
BufferedReader bufr = new BufferedReader(newInputStreamReader(System.in));//这句话一定要记住,利用键盘输入就是这个指令
//OutputStream out = System.out;
//OutputStreamWriter osw= new OutputStreamWriter(out);
BufferedWriter bfwr = new BufferedWriter(newOutputStreamWriter(System.out));
String line = null;
while ((line=bufr.readLine())!=null)//将输入的字符串转变大写
{
osw.write(line.toUpperCase());
bfwr.newLine();//只有在缓冲区才有readline这个函数,所以上面建立一个缓冲区
osw.flush();//每次写入之后,要刷新流,不然输出时没有字符串导入,输出为空
}
bufr.close();
}
}
流操作的基本规律:
最痛苦的就是流对象有很多,不知道该用哪一个。
通过三个明确来完成。
1,明确源和目的。
源:输入流。InputStream Reader
目的:输出流。OutputStream Writer。
2,操作的数据是否是纯文本。
是:字符流。
不是:字节流。
3,当体系明确后,在明确要使用哪个具体的对象。
通过设备来进行区分:
源设备:内存,硬盘。键盘
目的设备:内存,硬盘,控制台。
练习:
1,将一个文本文件中数据存储到另一个文件中。复制文件。
源:因为是源,所以使用读取流。 Reader
是不是操作文本文件。
是!这时就可以选择FileReader
这样体系就明确了。
接下来明确要使用该体系中的哪个对象。
明确设备:硬盘。上一个文件。
Reader体系中可以操作文件的对象是 FileReader
是否需要提高效率:是!。加入Reader体系中缓冲区 BufferedReader.
FileReader fr = new FileReader("a.txt");
BufferedReader bufr = new BufferedReader(fr);
目的:OutputStream Writer
是否是纯文本。
是!Writer。
设备:硬盘,一个文件。
Writer体系中可以操作文件的对象FileWriter。
是否需要提高效率:是!。加入Writer体系中缓冲区 BufferedWriter
FileWriter fw = new FileWriter("b.txt");
BufferedWriter bufw = new BufferedWriter(fw);
2,需求:将键盘录入的数据保存到一个文件中。
这个需求中有源和目的都存在。
那么分别分析
源:InputStream Reader
是不是纯文本?是!Reader
设备:键盘。对应的对象是System.in.
不是选择Reader吗?System.in对应的不是字节流吗?
为了操作键盘的文本数据方便。转成字符流按照字符串操作是最方便的。
所以既然明确了Reader,那么就将System.in转换成Reader。
用了Reader体系中转换流,InputStreamReader
InputStreamReader isr = new InputStreamReader(System.in);
需要提高效率吗?需要!BufferedReader
BufferedReader bufr = new BufferedReader(isr);
目的:OutputStream Writer
是否是存文本?是!Writer。
设备:硬盘。一个文件。使用 FileWriter。
FileWriter fw = new FileWriter("c.txt");
需要提高效率吗?需要。
BufferedWriter bufw = new BufferedWriter(fw);
转换流最重要的地方是将字节转换成字符时,可以转换成指定的码表
扩展一下,想要把录入的数据按照指定的编码表(utf-8),将数据存到文件中。
目的:OutputStream Writer
是否是存文本?是!Writer。
设备:硬盘。一个文件。使用 FileWriter。
但是FileWriter是使用的默认编码表。GBK.
但是存储时,需要加入指定编码表utf-8。而指定的编码表只有转换流可以指定。
所以要使用的对象是OutputStreamWriter。
而该转换流对象要接收一个字节输出流。而且还可以操作的文件的字节输出流。FileOutputStream
OutputStreamWriter osw = new OutputStreamWriter(newFileOutputStream("d.txt"),"UTF-8");
需要高效吗?需要。
BufferedWriter bufw = new BufferedWriter(osw);
所以,记住。转换流什么使用。字符和字节之间的桥梁,通常,涉及到字符编码转换时,需要用到转换流。
2 装饰设计模式
装饰设计模式
什么是装饰设计模式?
装饰和继承的区别?
装饰设计模式的特点?
装饰设计模式:
简述:当想对已有对象进行功能增强是,可定义类:将已有对象传入,基于已有对象的功能,并提供加强功能,那么自定义的该类称之为装饰类。即对原有类进行了优化。
装饰设计模式:
当想要对已有的对象进行功能增强时,
可以定义一个类,将已有对象传入,基于已有的功能,并提供加强功能
那么自定义的该类称为装饰类
装饰类通常会通过构造方法接受被装饰的对象
并基于被装饰的对象的功能,提供更详细的功能。
特点:装饰类通常都会通过构造方法接收被装饰的对象,并基于被装饰的对i型那个的功能提供更强的功能。
装饰和继承的区别:
1)装饰模式比继承要灵活,通过避免了继承体系的臃肿,且降低了类与类间的关系。
2)装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强的功能,所以装饰类和被装饰的类通常都是属于一个体系。
3)从继承结构转为组合结构。
注:在定义类的时候,不要以继承为主;可通过装饰设计模式进行增强类功能。灵活性较强,当装饰类中的功能不适合,可再使用被装饰类的功能。
要继承相应的父类,就需要将所有的抽象方法实现,或交给子类实现。其中MyBufferedReader的例子就是最好的装饰设计模式的例子,就是对BufferedReader的增强。
举例:
1 class Person
2 {
3 public void chifan()
4 {
5 System.out.println("吃饭");
6 }
7 }
8 class SuperPerson
9 {
10
11 private Person p;
12 SuperPerson(Person p)
13 {
14 this.p=p;
15 }
16 public void superChifan()
17 {
18 System.out.println("开胃酒");
19 p.chifan();
20 System.out.println("甜点");
21 System.out.println("吸根烟");
22 }
23
24 }
25 class PersonDemo
26 {
27 public static void main(String[] args)
28 {
29 Person p=new Person();
30 // p.chifan();
31 SuperPerson sp=new SuperPerson(p);
32
33 sp.superChifan();
34 }
35
36 }
[java] view plaincopy
37 /*
38 明白了BufferedReader类中特有方法readLine的原理后,
39 可以自定义一个类中包含一个功能和readline一致的方法
40 来模拟一下BufferedReader
41 */
42 import java.io.*;
43
44 class MyBufferedReader extends Reader
45 {
46
47 //装饰设计模式
48 private Reader r=null;
49
50 MyBufferedReader(Reader r)
51 {
52 this.r=r;
53 }
54 //可以一次读一行数据的方法
55 public String myReadLine() throws IOException
56 {
57 //定义一个临时容器,员BufferedReader封装的是字符数组
58 //为了演示方便,定义一个StringBulilder容器,因为最终还是要将数据变成字符串。
59 StringBuilder sb=new StringBuilder();
60 int ch=0;
61 while((ch=r.read())!=-1)
62 {
63 if(ch=='\r')
64 continue;
65 if(ch=='\n')
66 return sb.toString();
67 else
68 sb.append((char)ch);
69 }
70 //如果没有遇到\n,sb中而且有数据的话也要返回
71 if(sb.length()!=0)
72 return sb.toString();
73 return null;
74 }
75 /*
76 覆盖类中的抽象方法
77 */
78 public int read(char[] cbuf,int off,int len)throws IOException
79 {
80 return r.read(cbuf,off,len);
81 }
82
83 public void close() throws IOException
84 {
85 r.close();
86 }
87
88 public void myClose() throws IOException
89 {
90 r.close();
91 }
92 }
93
94
95
96 class MyBufferedReaderDemo
97 {
98 public static void main(String[] args) throws IOException
99 {
100 FileReader fr=new FileReader("buf.txt");
101
102 MyBufferedReader myBuf=new MyBufferedReader(fr);
103
104 String line=null;
105
106 while((line=myBuf.myReadLine())!=null)
107 {
108 System.out.println(line);
109 }
110
111 myBuf.myClose();
112 }
113
114 }
MyReader//专门用于读取数据的类。
|--MyTextReader
|--MyBufferTextReader
|--MyMediaReader
|--MyBufferMediaReader
|--MyDataReader
|--MyBufferDataReader
class MyBufferReader
{
MyBufferReader(MyTextReader text)
{}
MyBufferReader(MyMediaReader media)
{}
}
上面这个类扩展性很差。
找到其参数的共同类型。通过多态的形式。可以提高扩展性。
class MyBufferReader extendsMyReader
{
private MyReader r;
MyBufferReader(MyReader r)
{}
}
MyReader//专门用于读取数据的类。
|--MyTextReader
|--MyMediaReader
|--MyDataReader
|--MyBufferReader
以前是通过继承将每一个子类都具备缓冲功能。那么继承体系会复杂,并不利于扩展。
现在优化思想。单独描述一下缓冲内容。将需要被缓冲的对象。传递进来。也就是,谁需要被缓冲,谁就作为参数传递给缓冲区。
这样继承体系就变得很简单。优化了体系结构。
装饰模式比继承要灵活。避免了继承体系臃肿。而且降低了类于类之间的关系。
装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。
所以装饰类和被装饰类通常是都属于一个体系中的。
自己的语言描述:继承太臃肿,复杂。利用装饰设计模板,把原来的继承结构变成组合结构,这样多出来的一个类就可以实现前面3个类共性功能,同时将一些新的功能封装到自身里面以达到加强的作用,有继承结构变成组合结构,灵活性强,而且降低了类与类之间的关系。
自定义装饰类
如何自定义?
自定义装饰类只需要继承父类,如Reader,将原有的函数覆写并修改其函数内容即可
public int read(char[] cbuf, int off, int len) throwsIOException
{
return r.read(cbuf,off,len) ;
}
public void close()throws IOException
{
r.close();
}
LineNumberReader的用法?原理代码是什么?
LineNumberReader就是一个装饰类,在BufferedReader的基础之上,添加了编辑行号的功能
import java.io.*;
class LineNumberReaderDemo //在BufferedReader的基础之上,添加了编辑行号的功能,LineNumberReader
{
public static void main(String[] args) throws IOException
{
FileReader fr = new FileReader("装饰与继承.java");
LineNumberReader lnr = newLineNumberReader(fr);
String line = null;
lnr.setLineNumber(100);//LineNumber中自带的函数setLineNumber(),可以设置当前行号。设置100就从100开始输出
while((line=lnr.readLine())!=null)
{//getLineNumber()获取行号。
System.out.println(lnr.getLineNumber()+":"+line);
}
lnr.close();
}
}
3 LineNumberReader类
在BufferedReader中有个直接的子类LineNumberReader,其中有特有的方法获取和设置行号:setLineNumber()和getLineNumber()
原理:LineNumberReader中有一个计数器,定义一个Reader流对象,当读到流对象的时候才能进行行号的添加
原理例子:
import java.io.*;
class MyLineNumberReaderextends MyBufferedReader//建立一个类,可以实现LineNumberReader的功能
{//因为LineNumberReader继承了BufferedReader,并且覆写了readline()方法,可以推测出通过覆写该方法来装饰BufferedReader得到LineNumberReader,所以MyLineNumberReader也可以继承MyBufferedReader来简化代码
private int lineNumber;//私有化lineNumber可以用来记录行数。FileReader r不应再定义因为父类中有,可以直接拿来用
public void setLineNumber(int lineNumber)
{
this.lineNumber = lineNumber;//定义setLineNumber,可以将setLineNumber()中的对象赋值给本类变量lineNumber
}
public int getLineNumber()//getLineNumber()获得本类中lineNumber,返回值为int
{
return lineNumber;
}
MyLineNumberReader (FileReader r)//构造函数
{
super(r);//直接调用父类中的构造函数
}
public String myReadLine()throws IOException//建立myReadLine(),实现可以一次读一行数据的方法。
{ //定义一个临时容器。原BufferReader封装的是字符数组。
//为了演示方便。定义一个StringBuilder容器。因为最终还是要将数据变成字符串。
lineNumber++;//每次调用myReadLine()函数,linenumber就自加一次
return super.myReadLine();//返回父类中的myReadLine()函数方法值,简化了代码。注意是返回!
}
}
class MyLineNumberReaderDemo
{
public static void main(String[] args) throws IOException
{
FileReader fr = new FileReader("装饰与继承.java");//源文件与流关联
MyLineNumberReader mylnr = new MyLineNumberReader(fr);//使用自己的方法来读取fr
String line = null;
mylnr.setLineNumber(100);//初始设置LineNumber就为100,这样LineNumber从100就开始计数了。
while ((line=mylnr.myReadLine())!=null)
{
System.out.println(mylnr.getLineNumber()+":"+line);//输出LineNumber的数值和line
}
mylnr.myClose();//使用自己的函数关闭流
}
}
第一一个自己的类:
示例:
[java] view plaincopy
115 import java.io.*;
116
117 class MyLineNumberReader extends MyBufferedReader
118 {
119 private Reader r;
120 private int lineNumber;
121 MyLineNumberReader(Reader r)
122 {
123 super(r);
124 }
125 public String myReadLine() throws IOException
126 {
127
128 lineNumber++;
129 return super.myReadLine();
130 }
131
132 public void setLineNumber(int lineNumber)
133 {
134 this.lineNumber=lineNumber;
135 }
136 public int getLineNumber()
137 {
138 return lineNumber;
139 }
140 }
141
142 /*
143 class MyLineNumberReader
144 {
145 private Reader r;
146 private int lineNumber;
147 MyLineNumberReader(Reader r)
148 {
149 this.r=r;
150 }
151 public String myReadLine() throws IOException
152 {
153
154 lineNumber++;
155 StringBuilder sb=new StringBuilder();
156 int ch=0;
157
158 while((ch=r.read())!=-1)
159 {
160 if(ch=='\r')
161 continue;
162 if(ch=='\n')
163 return sb.toString();
164 else
165 sb.append((char)ch);
166 }
167 if(sb.length()!=0)
168 return sb.toString();
169 return null;
170 }
171
172 public void setLineNumber(int lineNumber)
173 {
174 this.lineNumber=lineNumber;
175 }
176 public int getLineNumber()
177 {
178 return lineNumber;
179 }
180
181 public void myClose()throws IOException
182 {
183 r.close();
184 }
185
186 }
187 */
188
189 class MyLineNumberReaderDemo
190 {
191 public static void main(String[] number) throws IOException
192 {
193 FileReader fr=new FileReader("copyTextByBuf.java");
194
195 MyLineNumberReader mylnr=new MyLineNumberReader(fr);
196
197 String line=null;
198 mylnr.setLineNumber(100);
199 while((line=mylnr.myReadLine())!=null)
200 {
201 System.out.println(mylnr.getLineNumber()+"::"+line);
202 }
203 mylnr.myClose();
204 }
205 }
字符流 字节流 总结
1. 文件的读取方式
|-- FileReader这个对象读取文件,文本文件
|-- 通过这个对象的read()方法来实现,文件结束返回-1
|-- 通过这个对象的read(buf[])来实现,读一批的效果,提高效率
返回值,就是数组存储有效字符的个数
2. 通过IO技术对文本文件进行复制
|-- 读取文件对象
|-- 写入文件对象
|-- 读一个写一个
|-- 读一批写一批,利用的是数组形式来完成
|-- 两个复制的案例,一个是用数组,一个不用,用数组的必须要会
3. 输出流的缓冲区
|-- BufferedWriter,提高输出流效率
|-- 建立缓冲区对象的时候,需要传递输出流对象,为的是提高次输出流的效率
|-- newLine()写一个换行,跨平台性
4. 输入流的缓冲区
|-- BufferedReader ,提高输入流的效率
|-- 建立缓冲区对象的时候,需要传递输入流对象,为的是提高次输入流的效率
|-- readLine()读取一行,返回的是字符串,读到结尾返回null,不返回换行符
5. 利用缓冲区对文本文件进行复制 *****
|-- 需要输出流对象,输入流对象
|-- 需要缓冲输出流对象,缓冲输入流对象
|-- 读一行,写一个,写一个换行
|-- 异常处理
6.IO对象小结
|-- 字符流对象
|-- 输出流
|-- Write
|-- FileWriter
|-- BufferWriter
|-- 输入流
|-- Reader
|-- FileReader
|-- BufferedReader
7. 装饰设计
|-- 对已经有的对象的0功能,进行增强,额外的为对象添加功能
|-- 已经有了人对象,吃饭的功能已经落后,需要增加功能
|-- 为人这个对象,对他的吃饭的功能,进行增强,搞了一个类去增强人对象的吃饭功能
|-- 增强功能的类,称为人类的装饰类
|-- 装饰设计模式,发现原有的功能已经不能满足现在的需求,搞个装饰类,对原有的对象进行装饰
8. 继承和装饰模式的区别
|-- 继承是面向对象三大特征之一
|-- 装饰模式,是为了解决现实中的问题而产生的
|-- 读取文本文件 TextReader
|--BufferedTextReader extends TextReader
|-- 读取图片文件 PicReader
|-- BufferedPicReader extends PicReader
|-- 读取网络数据 NetReader
|-- BufferedNetReader extends NetReader
|-- 读取视频数据 VideReader
|-- BufferedVideoReader extens VideoReader
|-- 解决继承体系过于臃肿,采用装饰模式
|-- Reader
|-- TextReader
|-- PicReader
|-- NetReader
|-- VideReader
|-- MP3Reader
|-- BufferedReader(Reader r) extends Reader
|-- 继承体系臃肿而且庞大,灵活性还差
|-- 装饰设计模式,体系简洁的多 灵活性好
9. 自己定义装饰类,装饰Reader类*****
|-- 自己写一个readLine()方法
|-- 返回的是字符串
|-- 返回的是文本中一行,但是没有换行符
10. 字节流 -- 什么类型文件都可以操作
|-- 输出流基类 OutputStream
|-- FileOutputStream对文件进行写入操作,写入的是一个字节数组
|-- 输入流基类 InputStream
|-- FileInputStream对文件进行读取,用字节数组来实现缓冲,提高效率
read() write() 字节数组 "".getBytes()
|-- 读一个写一个的复制文件
|-- 利用数组缓冲来复制文件
|-- 作业,利用API中字节流缓冲区对象,复制文件
本篇博文结束!
@感谢老师的辛苦批阅