------<a href="
http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
一、IO流
要把数据逐一输出到某个设备中,或者从某个设备中逐一读取数据,不管输入输出设备是什么,我们要用统一的方式来完成这些操作,用一种抽象的方式进行描述,这个抽象描述方式起名为IO流。Java对数据的操作是通过流的方式,用于操作流的对象都在IO包中。
流按流向分为:输入流和输出流。
流按操作数据分为两种:
字符流:抽象基类Reader,Writer。字符流只用于处理文字数据,原理是字节流读取文字字节数据后,不直接操作而是先查指定的编码表,获取对应的文字,再对这个文字进行操作。
字节流:抽象基类:InputStream,OutputStream。基本操作与字符流类相同。但它不仅可以操作字符,还可以操作其他媒体文件。
二、字符流
1.字符流的写入
import java.io.FileWriter;
import java.io.IOException;
public class WriterDemo {
public static void main(String[] args) {
//创建一个FileWriter对象并指定文件
//该目录下有同名文件会被覆盖
FileWriter fw = null;
try
{
fw = new FileWriter("demo.txt");
//往字符流中写入数据
fw.write("java01");
}
catch(IOException e)
{
e.printStackTrace();
}
//关闭资源,刷新流中缓冲的数据
finally
{
try
{
if(fw!=null)
fw.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
2.字符流的读取
import java.io.FileReader;
import java.io.IOException;
public class ReaderDemo {
public static void main(String[] args) throws IOException {
read1();
System.out.println("----------");
read2();
}
public static void read1() throws IOException
{
//创建FileReader对象,指定要读取的文件
//如果不存在,会发生FileNotFoundException
FileReader fr = new FileReader("demo.txt");
//第一种读取方式,使用read()方法
//每次读一个字符,并自动向下读取
//读取到结尾返回-1
int num = 0 ;
while((num = fr.read())!=-1)
{
System.out.println((char)num);
}
fr.close();
}
public static void read2() throws IOException
{
//创建FileReader对象,指定要读取的文件
//如果不存在,会发生FileNotFoundException
FileReader fr = new FileReader("demo.txt");
//第二种读取方式,使用int read(char[] cbuf,int off,int len)方法
//创建一个字符数组,将读取到的字符先存入数组当中
//返回读取的字符数,如果已到达流的末尾,则返回 -1
char [] ch = new char[1024];
int num = 0 ;
while((num = fr.read(ch))!=-1)
{
System.out.println(new String(ch,0,num));
}
fr.close();
}
}
总结练习:复制文本文件
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CopyText {
public static void main(String[] args) {
FileWriter fw = null;
FileReader fr = null;
try {
//创建字符写入流,指定目的地
fw = new FileWriter("demo1.txt");
//创建字符读取流,关联指定文件
fr = new FileReader("./src/test/day4/MapDemo.java");
//建立一个字符数组,临时存储读取流读取的数据,并使用写入流写入指定文件
char[] ch = new char[1024];
int num = 0;
while ((num = fr.read(ch)) != -1) {
fw.write(ch, 0, num);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fw != null)
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
if (fr != null)
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3.字符流的缓冲区
缓冲区的出现是为了提高流的操作效率而出现的,所以在创建缓冲区之前,必须要先有流对象,作为参数传递给缓冲区的构造函数。
通过缓冲区复制文本文件
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedCopy {
public static void main(String[] args) {
//创建缓冲区,将文本写入字符输出流,缓冲各个字符
//创建缓冲区,从字符输入流中读取文本,缓冲各个字符
BufferedWriter bfw = null;
BufferedReader bfr = null;
try {
//将需要提高效率的流对象作为参数传递给缓冲区的构造函数
bfw = new BufferedWriter(new FileWriter("demo2.txt"));
bfr = new BufferedReader(new FileReader("./src/test/day4/MapDemo.java"));
//读取一个文本行将其写入流中,再写入一个行分隔符,需要刷新缓冲。
String str = null;
while((str = bfr.readLine()) != null)
{
bfw.write(str);
bfw.newLine();
bfw.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bfw != null)
try {
bfw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (bfr != null)
try {
bfr.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
明白了BufferedReader类中特有方法readLine的原理后,可以自定义一个类中包含一个功能和readLine一致的方法来模拟一下BufferedReader
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
class MyBuffer extends Reader
{
private Reader r ;
MyBuffer(Reader r)
{
this.r = r ;
}
//模拟一个readLine方法
public String myReadLine() throws IOException
{
//定义一个临时容量存储读到的每个字符并判断
//因为每行结尾是\r\n,读到\r接着往下判断,读到\n就到了结尾
StringBuilder sb = new StringBuilder();
int num = 0 ;
while((num = r.read())!=-1)
{
if(num == '\r')
continue;
if(num == '\n')
return sb.toString();
else
sb.append((char)num);
}
if(sb.length()!=0)
return sb.toString();
return null;
}
//覆盖Reader中的抽象方法
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
// TODO Auto-generated method stub
return r.read(cbuf, off, len);
}
@Override
public void close() throws IOException {
// TODO Auto-generated method stub
r.close();
}
}
public class MyBufferedReader {
public static void main(String[] args) throws IOException {
//使用自定义的缓冲区,过程与BufferedReader一样
MyBuffer mb = new MyBuffer(new FileReader("./src/test/day4/CollectionDemo.java"));
String str = null;
while((str = mb.myReadLine()) != null)
{
System.out.println(str);
}
mb.close();
}
}
三、装饰设计模式
装饰模式是一种比较常见的模式,动态地给一个对象添加一些额外的职责。是对继承的有力补充,解决类膨胀的问题,降低类与类之间的耦合,具有非常好的扩展性。
//定义人的类,具有一个吃饭的方法
class Person
{
public void eat()
{
System.out.println("吃饭");
}
}
//定义西方人的类,用装饰的方式增强Person类
class Western
{
private Person p ;
Western(Person p)
{
this.p = p;
}
public void eat()
{
System.out.println("开胃酒");
p.eat();
System.out.println("甜点");
}
}
//定义中国人的类,用继承的方式增强Person类
class Chinese extends Person
{
public void eat()
{
super.eat();
System.out.println("喝汤");
}
}
public class DecoratorDemo {
public static void main(String[] args) {
Person p = new Person();
Western w = new Western(p);
w.eat();
System.out.println("-----------");
Chinese c = new Chinese();
c.eat();
}
}