IO流与NIO流讲解区分
1.io:input+output
》》》input 和out 是对计算机本身而言的,input是往计算机中输入,对计算机而言就是读,反之,out 就是从计算机往外输出 就是写;
》》》相对于CPU而言的,in就是进来,进去到CPU中,所以就为读取了
IO最简单的一种记法就是 读写,I 就是读,O 就是写。
2.IO流的分类:
》》》输入流:inputStream、Reader
输出流:outputStream、Writer
》》》字节流:inputStream、outputStream,字节流功能更强大
字符流:Reader、Writer
》》》节点流:以数据源为节点的流称为节点流
fileInputStream、fileOutputStream、fileReader、fileWriter
处理流:处理以流为源头的流(包装流)
dataInputStream、ObjectInputStrem、BufferedInputStream、BufferedOutputStream
3.关于流在开发中常用的方法:
3.1 file file=new file(path);
//字节流–文件实现流
fileInputStream fis=new fileInputStream(file);
fileoutputStream fos=new fileoutputStream (file);
//流的写入读出:比如数据库就是这样:查询—读出;插入更新—写入
读出:(内部的流读出去)/ 写入:(外部来的流写入)
3.2 把 A中的文件复制到B中,先把内部的流读出来,放到一个容器,再把读出来的流写入文件中:
int count=fis.read();
fos.write(value);
字符流–实现流
3.3 fileReader fr=new fileReader(file);
fileWriter fw=new fileWriter (file);
3.4 流的读取和写入
fr.read();
fw.write();
3.5 byte[] buf = new byte[1000];
int count = fis.read(buf);
//表示每次读多少字节
char[] cbuf = new char[10];
int count = 0;
while((count = fr.read(cbuf)) != -1){
fw.write(cbuf, 0, count);
//表示每次读取多少个字符
4.flush()
》》》flush 方法 值针对于输出流,字符和字节输出流。
》》》如果一个输出流,存在缓冲区(提高写出的效率,避免多次IO、操作),而且不能及时的关闭掉输出流,那么需要考虑使用flush()方法,来刷新缓冲区中的缓存的数据。
》》》实际开发中可以只关闭处理流(包装流)即可;一般流的关闭顺序是相反的,先开启的后关闭;后开启的先关闭。
5.BufferedInputStream:带缓冲区了字节输入流。
BufferedOutputStream:带缓冲区的字节输出流。
使用方式--复制文件:
file f=new file(path);
FileInPutStream fis=new FileInPutStream (f);
BufferedInputstream bis=new BufferedInputstream (fis);
//BufferedInputstream 对FileInPutStream 使用了装饰者模式,把FileInPutStream 的效率和读写速度提高了。
int value=bis.read();
FileOutPutStream fos=new FileOutPutStream (f);
BufferedOutPutStream bos=new BufferedOutPutStream (fos);
int value=bos.write(value);
》》》如果想对一个方法进行增强它的功能,可以使用继承的方式,重写需要被增强的方法。
》》》如果使用继承,那么只能重写它直接父类的某些方法。
》》》 如果想对多个类的方法做增强,那么都要写出对应的带缓冲区的增强类。
》》》使用组合的模式,想增强哪个类,传入哪个类的对象即可。
比如,想增强FileInpuStream ,传入FileInputStream 对象即可。 想增强 DataInputStream 那么传入DataInputStream 对象即可。
5.效率问题
》》》BufferedInputStream和BufferedOutputStream效率比FileInPutStream 和 FileOutPutStream 高;因为带缓冲的文件文件操作流先把数据带到缓冲区,再从缓冲区读取写入,这样的效率更高;结束关闭流之前需要先flush()输出流和close()流。
6.装饰设计模式
装饰设计模式,可以在原有技能的基础上,新增技能,降低继承所带来的耦合性。
代码示例:在人吃饭的基础上,添加了人做饭、运动和学习的功能
public class Test1 {
public static void main(String[] args) {
SuperPerson person = new SuperPerson(new Person());
person.tech();
}
}
//技能接口
interface Tech(){
public void tech();
}
//没有追求的人的方法
Class person implements Tech{
@override
public void tech(){
System.out.println("吃饭");
System.out.println("睡觉");
}
//提升和包装个人形象
Class SuperPerson implements Tech{
private Person person;
public SuperPerson (Person person){
this.SuperPerson =person
}
@override
public void tech(){
System.out.println("学习");
System.out.println("做饭");
System.out.println("打游戏");
}
//最终这个人拥有了:学习,做饭,游戏等和别人不一样的特性
}
7.字符输入流和字符输出流
BufferedReader:带缓冲区的字符输入流。
BufferedWriter:带缓冲区的字符输出流。
实现文件复制的代码演示:
BufferedReader br = new BufferedReader(new FileReader("./res/2.txt"));
BufferedReader bw = new BufferedWriter(new FileWriter("./res/2_copy.txt"));
//读取一行文本数据,一旦遇到了换行符就返回\r\n \n是作为方法返回的条件的。
//返回读取到的一行数据,不包含\r\n 如果读取到了流的末尾 返回null
String str = br.readLine();
while(str != null){
bw.write(str); //往输出流中写出一个当前系统的换行符 平台无关性
bw.newLine();
str = br.readLine();
}
br.close();
bw.close();
8.readLine() 原理—逐行读取
从字节数组缓冲区中,逐个读取字符,将读取到的字符放置到一个StringBuilder 中。一旦读取到的字符为当前系统的换行符。方法返回,返回StringBuilder 中的所有的字符,不包含\r\n
9.补充知识:
》》》LineNumberReader:功能字符输入流,功能:给每行读取到的数据对应一个行号。
》》》代码示例:
LineNumberReader lnr = new LineNumberReader(new FileReader("./src/com/bjsxt/io/LineNumberReaderTest.java"));
//设置起始行号
lnr.setLineNumber(100);
String str = null;
while((str = lnr.readLine())!= null){//打印行号+内容
System.out.println(lnr.getLineNumber()+" "+str);
}
10 转换流:
》》》InputStreamReader:转换流 从字节到字符的转换。 解码过程
作用类似于:string s=new string(bity[],0,buf);解码过程
InputStreamReader涉及到的设计模式:适配器设计模式。Adapter
计算机中使用的是:字符
》》》OutputStreamWriter:转换流 自字符到字节 编码过程
编码: 从明文到密文
解码:从密文到明文
作用类似:getByte[ ] 编码
使用方法:
解码:需要转化成字节,然后使用字节流把字节写出来
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
读入计算机的数据要解码才能让计算机识别和使用;
编码:
Writer out = new BufferedWriter(new OutputStreamWriter(System.out));
从计算机中写出的文件要编码成人类可以识别的文字。
》》》 InputStreamReader isr = new InputStreamReader(new FileInputStream ("./res/7.txt"),“UTF-8”);
BufferedReader br = new BufferedReader(isr);
11. PrintStream:打印流----是OutputStream的子类
》》》提供了针对所有的类型转换为字符串,并将字符串转换为字节的写出去的方法。
》》》永远不会抛出IOException。可以通过checkError()去查看内部的异常情况。
》》》提供了自动刷新的功能。
》》》System.out 就是这个类的实例
13. 打印异常信息流
try{ }
catch (FileNotFoundException e1) {
e1.printStackTrace(); }
13.使用须知
》》》1:读取文本文件 使用FileReader进行读取,为了提高效率,用BufferedReader 对FileReader进行装饰。
new BufferedReader(new FileReader(filename)); readLine()
》》》2:写出文本文件 使用FileWriter进行写出,为了提高效率,使用BufferedWriter 对FileWriter 进行装饰。
new BufferedWriter(new FileWriter(fileName)); write(String str) newLine()
》》》3:读取非纯文本数据 FileInputStream 为了提高效率 使用BufferedInputStream 对FileInputStream 进行装饰。
new BufferedInputStream(new FileInputStream(fileName);
》》》4:写出非纯文本数据 FileOutputStream 为了提高效率 使用BufferedOutputStream 对 FileOutputStream 进行装饰。
new BufferedOutputStream(new FileOutputStream(fileName));
》》》5.带缓冲区的流,缓冲区默认大小 8192。
14 .适配器设计模式
/**
- 适配器设计模式
- 模拟,手机充电器的工作过程。
- 手机充电器需要5V,电压是220V,那么就需要一个适配的中转器来实现
- 这里就是通过继承和重写run()方法来实现。
*/
public class AdapterTest {
public static void main(String[] args) {
Adapter adapter = new Adapter();
adapter.run();
OtherAdapter adapter2 = new OtherAdapter(new Adaptee());
adapter2.run();
}
}
//类的适配器设计模式。
//提供原始电压的对象
class Adaptee{
public void run(){
System.out.println(“我提供了220V电压供你工作”);
}
}
//充电器对象对应的类型
class Adapter extends Adaptee{
@Override
public void run() {
super.run();
System.out.println(“提供的220V电压,被转换为了5V”);
}
}
//对象适配器模式 描述的是最终工作的对象的规则
interface Target{
//你要给我提供5V的电压
public void run();
}
//手机充电器OtherAdapter 具体的某一个充电器
class OtherAdapter implements Target{
private Adaptee adaptee;
public OtherAdapter( Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void run() {
adaptee.run();
System.out.println(“220—>5”);
}
}
15.万能输入输出流
DataInputStream、DataoutputStream
具体的代码:
》》》 //写出各种类型的数据
DataOutputStream dos = new DataOutputStream(new
BufferedOutputStream(new FileOutputStream("./res/10.txt")));
dos.writeByte(12);//00001010 1
dos.writeShort(12);//2
dos.writeInt(12);
dos.writeLong(12L);
dos.writeFloat(1.0f);
dos.writeDouble(1.2);
dos.writeBoolean(false);
dos.writeChar(‘a’);
dos.writeChars(“你好啊”);
》》》读取各种类型的数据
DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream("./res/10.txt")));
System.out.println(dis.readByte());
System.out.println(dis.readShort());
System.out.println(dis.readInt());
System.out.println(dis.readLong());
System.out.println(dis.readFloat());
System.out.println(dis.readDouble());
System.out.println(dis.readBoolean());
System.out.println(dis.readChar());
System.out.println(dis.readChar());
System.out.println(dis.readChar());
System.out.println(dis.readChar());