一、IO流简述------用于操作数据的
IO流用来处理设备之间的数据传输;
Java对数据的操作是通过流的方式;
Java用于操作流的对象都是在IO包中;
流按操作数据分为: 字节流(通用)和字符流; 按流向分为: 输入流和输出流.
字节流的抽象基类:
InputStream , OutputStream
字符流的抽象基类:
Reader, Writer
注: 由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。
如: InputStream的子类FileInputStream ;Reader的子类FileReaderStream。
二、
字节流的两个基类:
InputStream , OutputStream
字符流的两个基类:(专门处理文本和数据)
Reader, Writer
--------->>>字符流
先以操作文件为主来演示
要求: 在硬盘上,创建一个文件并写入一些文字数据
找到一个专门用于操作文件的Writer子类对象.FileWriter。 后缀名是父类名。 前缀是该流对象的功能。
创建一个FileWriter对象,该对象一被初始化就必须要明确被操作的文件;
而且该文件会被创建到指定目录下,如果该目录下已有同名文件,将该文件覆盖;
其实该步就是在明确数据要存放的目的地 :
FileWriter fw = new FileWriter("demo.txt");
调用write方法,将字符串写入到流中:
fw.writer("abcdef");
刷新流对象中的缓冲中数据 ,将数据刷到目的地中:
fw.flush();
关闭流资源,但是关闭之前会刷新一次内部的缓冲区的数据; 将数据刷新到目的地中。
和flush区别: flush刷新后,流可以继续使用,close刷新后,会将流关闭:
fw.close();
IO异常的处理方式:
请看代码:
import java.io.*; calss FileWriterDemo { public static void main(String[] args) { FileWriter fw = null; try { fw = new FileWriter("demo.txt"); fw.write("safdasf"); }catch(IOException) {
System.out.println("catch:"+e.toString());
}
finally {
try {
if(fw!=null)
fw.close();
}catch(IOException) {
System.out.println("catch:"+e.toString());
}
}
}
}
文件的续写:
传递一个true参数,代表不覆盖已有的文件,并在已有文件的末尾处进行数据续写:
FileWriter fw = new FileWriter("Demo.txt",true);
文本文件的读取:
方式一:
创建一个文件读取流对象,和指定名称的文件相关联;
要保证该文件是已经存在的,如果不存在,会发生异常 FileNotFoundException 。
FileReader fw = new FileReader("Demo.txt");
调用读取流对象的read方法:
read(): 一次读一个字符,而且会自动往下读。
While((ch = fr.read()) != -1) {
System.out.println("ch="+(char)ch);
}
方式二:
FileReader fw = new FileReader("Demo.txt");
/* 定义一个字符数组,用于存储读到字符;
该read(char[]) 返回的是读到字符个数 */:
char[] buf = new char[1024];
int num = 0;
while((num=fr.read(buf)) != -1) {
System.out.println(new String(buf, 0, num));
}
小练习: 读取一个.java 文件, 并打印在控制台上。
拷贝文本文件:
将C盘一个文件文本复制到D盘:
复制的原理——>其实就是将C盘下的文件数据存储到D盘的一个文件中
步骤:
1、在D盘创建一个文件,用于存储C盘文件中的数据。
2、定义读取流和C盘文件关联;
3、通过不断的读写完成数据存储;
4、关闭资源
一个实现了复制功能的Copy类:
1 public static void Copy() { 2 FileWriter fw = null; 3 FileReader fr = null; 4 try { 5 fw = new FileWriter("Demo_copy.txt"); 6 fr = new FileReader("Demo.java"); 7 char [] buf = new char[1024]; 8 int len = 0; 9 while((len = fr.read(buf)) != -1) { 10 fw.write(buf, 0, len); 11 } 12 } catch(IOException e) { 13 throw new RuntimeException("读写失败"); 14 } 15 finally { 16 if(fr != null) 17 try { 18 fr.close(); 19 }catch(IOException e) { 20 21 } 22 if(fw != null) 23 try { 24 fw.close(); 25 }catch(IOException e) { 26 27 } 28 } 29 }
字符流的缓冲区:
简述:
缓冲区的出现提高了对数据的读写效率。
对应类:
|--BufferedWriter //将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效率写入
|--BufferedReader //从字符输入流中读取文本、缓冲各个字符,从而实现字符、数组和行的高校读取。
缓冲区要结合流才可以使用; 在流的基础上对流的功能进行了增强。
——>>BufferedWriter
缓冲区的出现是为了提高流的操作效率而出现的;
所以在创建缓冲区之前,必须要先有流对象;
该缓冲区中提供了一个跨平台的换行符: newLine()
创建一个字符写入流对象:
FileWriter fw = new FileWriter("buf.txt");
为了提高字符写入流效率,加入了缓冲技术
只要将需要提高的效率的流对象作为参数传递给缓冲区的构造函数即可:
BufferedWriter bufw = new BufferedWriter(fw);
写入:
for(int x=1; x<5; x++) {
bufw.writer("dfsfa"+x); bufw.newLine(); bufw.flush();
} //记住,只要用到缓冲区,就要记得刷新: bufw.flush();
其实关闭缓冲区就是在关闭缓冲区中的流对象:
bufw.close();
——>>BufferedReader
字符读取缓冲区:
该缓冲区提供了一个一次读取一行的方法 readLine(); 包含该行内容字符串,不包含任何行终止符,当返回null时 表示读到文件末尾。
无论是读一行,获取读取多个字符。其实最终都是在硬盘上一个一个读取。所以最终使用的还是read方法一次读一个的方法。
创建一个读取流对象和文件相关联:
FileReader fr = new FileReader("buf.txt");
为了提高效率,加入缓冲技术,将字符读取流对象作为参数传递给缓冲区对象的构造函数。
BufferedReader bufr = new BufferedReader(fr);
String line = null;
while((line = bufr.readLine()) != null) {
System.out.println(line);
}
bufr.close();
附加小练习: 自定义一个类中包含一个功能和readLine一致的方法,来模拟BufferedReader
装饰设计模式:
当想要对已有的对象进行功能增强时;
可以定义类,将已有对象传入,基于已有的功能,并提供加强功能;
那么自定义的该类称为装饰类。
装饰类通常都会通过构造方法接受被装饰的对象; 并基于被装饰的对象的功能,提供更强的功能。
例子:
1 class Person { 2 public void eat() { 3 System.out.println("吃饭"); 4 } 5 } 6 7 //装饰类 8 class SuperPerson { 9 private Person p; 10 SuperPerson(Person p) { 11 this.p = p; 12 } 13 public void superEat() { 14 System.out.println("一杯香槟"); 15 Person.eat(); 16 System.out.println("来点甜点"); 17 } 18 }
装饰和继承的区别:
装饰模式比继承要灵活,避免了继承体系的臃肿; 而且还降低了类与类之间的关系。
装饰类因为增强了已有对象,具备的功能和已有的是相同的,只不过是提供了更强的功能,所以装饰类和被装饰类通常是属于一个体系中的。
LIneNumberReade:
----带行号的装饰类
FileReader fr = new FileReader("PersonDemo.java");
LineNumberReader lnr = new LineNumberReader(fr);
String line = null;
lnr.setLineNumber(100):
while() {
System.out.println(lnr.getLIneNumber()+": "+line);
}
lnr.close();