流的概念
流可以这样理解:数据的流动,就是数据流。IO流最终要以对象来体现,对象都存在IO包中。
流的分类
1、根据数据的流向分为输入流和输出流,其中输入流只能读,输出流只能写
2、根据处理的数据不同分为字节流和字符流
字节流
处理字节数据的流对象。设备上的数据无论是图片或者dvd、文字,他们都以二进制存储的。二进制最终都是以8位字节为数据单元进行体现,所以计算机中的最小数据单元就是字节。意味着,字节流可以处理设备上的所有数据,所以字节流一样可以处理字符数据。
字符流
既然字节流可以处理所有的数据,那么为什么还要有字符流呢?因为字符每个国家都不一样,所以涉及到了字符编码的问题,那么GBK编码阿德中文用Unicode编码解析是有问题的,所以需要回去中文字节数据的同时加上指定的编码表才可以解析正确数据。为了方便文字的解析,所以将字节流和编码表封装成对象,这个对象就是字符流。只要操作字符数据,优先考虑使用字符流体系。
流的体系因为功能不同,但是有共性内容,不断抽取,形成集成体系。该体系一共有四个基类,而且都是抽象类。
字节流:InputStream OutputStream
字符流:Reader Writer
在这四个系统中,它们的子类,都有一个共性特点:子类名后缀都是父类名,前缀名都是子类的功能名称。
===================================================================================================================
package org.czty.io;
import java.io.FileWriter;
import java.io.IOException;
/**
* Created by Chris chen on 2017/8/4.
*/
public class Test1 {
public static void main(String[] args) throws IOException {//读写都会发生IO异常
/**
* @Author: Chris Chen
* @Description:1、创建一个字符输出流对象,用于操作文件。该对象一建立,就必须明确数据存储位置,是一个文件
* 2、对象产生后,会在堆内存中有一个实体,同时也调用了系统底层资源,在指定的位置创建了一个存储数据的文件
* 3、如果指定位置,出现了同名文件,文件会被覆盖
*/
FileWriter fileWriter = new FileWriter("d:/test.txt");//FileNotFoundException
/*调用Writer类中的write方法写入字符串。字符串并未直接写入到目的地中,而是写入到了流中,
(其实是写入到内存缓冲区中)。怎么把数据弄到文件中?*/
fileWriter.write("chris chen");
fileWriter.flush();//刷新缓冲区,将缓冲区中的数据刷到目的地文件中
fileWriter.close();//关闭流,其实关闭的就是Java调用的系统底层资源。在关闭前,会先刷新流
}
}
close()和flush()的区别
flush():将缓冲区的数据刷到目的地后,流可以使用
close():将缓冲区的数据刷到目的地后,流就关闭了,该方法主要用于结束调用底层资源。这个动作一定做。
===================================================================================================================
FileWriter写入数据的细节
1、Windows中的换行符:\r\n连个符号组成 Linux \n
2、续写数据,只要在构造函数中传入新的参数true
3、目录分隔符:windos\\ /
package org.czty.io;
import java.io.FileWriter;
import java.io.IOException;
/**
* Created by Chris chen on 2017/8/4.
*/
public class Test2 {
public static void main(String[] args) {
FileWriter fileWriter = null;
try {
fileWriter = new FileWriter("d:/test.txt",true);
fileWriter.write("abcde");
}catch (IOException e) {
System.out.println(e.toString()+"...");
}finally {
if (fileWriter != null) {
try {
fileWriter.close();
}catch (IOException e) {
System.out.println("close:" + e.toString());
}
}
}
}
}
======================================================================================================
FileReader:使用Reader体系,读取一个文本文件中的数据。返回-1,标识读到结尾
package org.czty.io;
import java.io.FileReader;
import java.io.IOException;
/**
* Created by Chris chen on 2017/8/4.
*/
public class Test3 {
public static void main(String[] args) throws IOException {
//创建可以读取文本文件的流对象,FileReader让创建好的流对象和指定的文件相关联
FileReader fileReader = new FileReader("d:/test.txt");
int ch = 0;
while ((ch = fileReader.read()) != -1) {//没有读到结尾
System.out.print((char) ch);//调用读取流的read方法,读取一个字符
}
fileReader.close();
}
}
===================================================================================================================
读取数据的第二种方式:自定义缓冲区。(第二种方式较为高效)
package org.czty.io;
import java.io.FileReader;
import java.io.IOException;
/**
* Created by Chris chen on 2017/8/4.
*/
public class Test4 {
public static void main(String[] args) throws IOException {
FileReader fileReader = new FileReader("d:/test.txt");//创建读取流对象和指定文件关联
//因为要使用read(char[])方法,将读取到的字符存入数组。所以要创建一个字符数组,一般数组的长度都是1024的整数倍
char[] chars = new char[1024];
int len = 0;
while ((len = fileReader.read(chars)) != -1) {
System.out.println(new String(chars,0,len));
}
fileReader.close();
}
}
===================================================================================================================
IO中使用到了一个设计模式:装饰设计模式
装饰设计模式解决:对一组类进行功能增强。
包装:写一个类(包装类)对被包装的对象进行包装
1、包装类和被包装对象要实现同样的接口
2、包装类要持有一个包装对象
3、包装类在实现接口时,大部分方法是靠调用被包装对象来实现的,对于需要修改的方法我们自己实现。