IO的分类
IO流分类:
如果是按照数据的流向划分:输入流与输出流。
如果按照处理的单位划分:字节流与字符流。
字节流:读取得都是文件中二进制数据,读取到二进制数据不会经过任何的处理。
字符流: 字符流读取的数据是以字符为单位的 。 字符流也是读取文件中的二进制数据,不过会把这些二进制数据转换成我们能 识别的字符。 字符流 = 字节流 + 解码
字节流
输入字节流:
--------| InputStream 所有输入字节流的基类 抽象类
------------| FileInputStream 读取文件数据的输入字节流
------------| BufferedInputStream 缓冲输入字节流 缓冲输入字节流的出现主要是为了提高读取文件数据的效率。 其实该类内部只不过是维护了一个8kb的字节数组而已。
输出字节流:
--------| OutputStream 是所有输出字节流 的父类。 抽象类
-----------| FileOutStream 向文件输出数据的输出字节流。
-----------| Bufferedoutputstream 缓冲输出字节流 BufferedOutputStream出现的目的是为了提高写数据的效率。 内部也是维护了一个8kb的字节数组而已。
FileOutputStream要注意的细节:
- 使用FileOutputStream 的时候,如果目标文件不存在,那么会自动创建目标文件对象,如果目标文件已经存在,那么会先清空目标文件中的数据,然后再写入数据。
- 使用FileOutputStream写数据的时候, 如果目标文件已经存在,需要在原来数据基础上追加数据的时候应该使用new FileOutputStream(file,true)构造函数,第二参数为true。
- 使用FileOutputStream的write方法写数据的时候,虽然接收的是一个int类型的数据,但是真正写出的只是一个字节的数据,只是把低八位的二进制数据写出,其他二十四位数据全部丢弃。
BufferedOutputStream 要注意的细节:
- 使用BufferedOutStream写数据的时候,它的write方法是是先把数据写到它内部维护的字节数组中。
- 使用BufferedOutStream写数据的时候,它的write方法是是先把数据写到它内部维护的字节数组中,如果需要把数据真正的写到硬盘上面,需要调用flush方法或者是close方法、 或者是内部维护的字节数组已经填满数据的时候。
public class Test {
public static void main(String[] args) {
Test test = new Test();
test.readFile();
}
public static void main(String[] args) {
Test test = new Test();
test.readFile();
}
public void readFile(){
FileInputStream input = null;
FileOutputStream out = null;
try {
input = new FileInputStream("/Users/alex/Downloads/img/img.png");
out = new FileOutputStream("/Users/alex/Downloads/img/img_copy.png");
byte[] buf = new byte[1024*8];
int length = 0;
while ( (length = input.read(buf)) != -1 ){
out.write(buf,0,length);
}
} catch (IOException e) {
System.out.println("拷贝图片出错...");
throw new RuntimeException(e);
}finally {
//原则: 先开后关,后开先关。
try {
if (out != null){
out.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
try {
if (input != null){
input.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
public class Test {
public static void main(String[] args) {
Test test = new Test();
test.readFile();
}
public static void main(String[] args) {
Test test = new Test();
test.readFile();
}
public void readFile2(){
FileInputStream input = null;
FileOutputStream out = null;
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream = null;
try {
input = new FileInputStream("/Users/alex/Downloads/img/img.png");
out = new FileOutputStream("/Users/alex/Downloads/img/img_copy.png");
bufferedInputStream = new BufferedInputStream(input);
bufferedOutputStream = new BufferedOutputStream(out);
int length = 0;
byte[] buf = new byte[1024];
while ( (length = bufferedInputStream.read(buf)) != -1 ){
bufferedOutputStream.write(buf,0,length);
}
bufferedOutputStream.flush();
} catch (IOException e) {
System.out.println("拷贝图片出错...");
throw new RuntimeException(e);
}finally {
//原则: 先开后关,后开先关。
try {
if (bufferedOutputStream != null){
bufferedOutputStream.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
try {
if (bufferedInputStream != null){
bufferedInputStream.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
字符流
输入字符流:
----------| Reader 输入字符流的基类(抽象类)
-------------| FileReader 读取文件的输入字符流。
-------------| BufferedReader 缓冲输入字符流缓冲输入字符流出现的目的是为了提高读取文件 的效率和拓展了FileReader的功能。其实该类内部也是维护了一个字符数组。
输出字符流:
-----| Writer 输出字符流的基类(抽象类)
-----------| FileWriter 向文件数据数据的输出字符流。
-----------| BufferedWriter 缓冲输出字符流缓冲输出字符流作用,提高FileWriter的写数据效率与拓展FileWriter的功能。BufferedWriter内部只不过是提供了一个8192长度的字符数组作为缓冲区而已,拓展了FileWriter的功能。
FileWriter要注意的事项:
- 使用FileWriter写数据的时候,FileWriter内部是维护了一个1024个字符数组的,写数据的时候会先写入到它内部维护的字符数组中,如果需要把数据真正写到硬盘上,需要调用flush或者是close方法或者是填满了内部的字符数组。
- 使用FileWriter的时候,如果目标文件不存在,那么会自动创建目标文件。
- 使用FileWriter的时候, 如果目标文件已经存在了,那么默认情况会先情况文件中的数据,然后再写入数据 , 如果需要在原来的基础上追加数据,需要使用“new FileWriter(File , boolean)”的构造方法,第二参数为true。
public class Demo2 {
public static void main(String[] args) throws IOException {
readTest2();
}
//使用缓冲字符数组读取文件。
public static void readTest2() throws IOException{
//找到目标文件
File file = new File("F:\\1208project\\day21\\src\\day21\\Demo1.java");
// 建立数据的输入通道
FileReader fileReader = new FileReader(file);
//建立缓冲字符数组读取文件数据
char[] buf = new char[1024];
int length = 0 ;
while((length = fileReader.read(buf))!=-1){
System.out.print(new String(buf,0,length));
}
}
public static void readTest1() throws IOException{
//找到目标文件
File file = new File("F:\\1208project\\day21\\src\\day21\\Demo1.java");
//建立数据的输入通道
FileReader fileReader = new FileReader(file);
int content = 0 ;
while((content = fileReader.read())!=-1){ //每次只会读取一个字符,效率低。
System.out.print((char)content);
}
//关闭资源
fileReader.close();
}
}
public class Test {
public static void main(String[] args) throws IOException {
//找到目标文件
File file = new File("/Users/alex/Downloads/img/test.txt");
//建立数据输出通道
FileWriter fileWriter = new FileWriter(file,true);
//准备数据,把数据写出
String data = "今天天气非常好!!";
fileWriter.write(data); //字符流具备解码的功能。
//刷新字符流
fileWriter.flush();
//关闭资源
fileWriter.close();
}
}
public class Test {
public static void main(String[] args) throws IOException {
}
public void copyByChar(){
FileWriter fileWriter = null;
FileReader fileReader = null;
try {
fileReader = new FileReader("/Users/alex/Downloads/img/a.txt");
fileWriter = new FileWriter("/Users/alex/Downloads/img/a_copy.txt");
int length = 0;
char[] chars = new char[1024];
while ( (length = fileReader.read(chars)) != -1 ){
fileWriter.write(chars,0,length);
fileWriter.flush();
}
}catch (IOException e){
throw new RuntimeException(e);
}finally {
try {
if (fileReader != null){
fileReader.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
try {
if (fileWriter != null){
fileWriter.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
public void copyByBuffered(){
BufferedReader bufferedReader = null;
BufferedWriter bufferedWriter = null;
try {
bufferedReader = new BufferedReader(new FileReader("/Users/alex/Downloads/img/a.txt"));
bufferedWriter = new BufferedWriter(new FileWriter("/Users/alex/Downloads/img/a_copy.txt"));
String line=null;
while((line = bufferedReader.readLine())!=null){
bufferedWriter.write(line);
bufferedWriter.newLine();
}
bufferedWriter.close();
bufferedReader.close();
}catch (IOException e){
throw new RuntimeException(e);
}finally {
try {
if (bufferedReader != null){
bufferedReader.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
try {
if (bufferedWriter != null){
bufferedWriter.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
装饰者设计模式
装饰者设计模式:增强一个类的功能,而且还可以让这些装饰类互相装饰。
BufferedReader是不是拓展了FileReader的功能。
BuferedWriter 也是拓展了FileWriter的功能。
需求1: 编写一个类拓展BufferedReader的功能, 增强readLine方法返回 的字符串带有行号。
需求2:编写一个类拓展BufferedReader的功能, 增强readLine方法返回 的字符串带有分号。
需求3: 编写一个类拓展BufferedReader的功能, 增强readLine方法返回 的字符串带有双引号。
需求4: 编写一个类拓展BufferedReader的功能, 增强readLine方法返回 的字符串带有行号+ 分号。
需求5: 编写一个类拓展BufferedReader的功能, 增强readLine方法返回 的字符串带有分号+ 双引号。
需求6: 编写一个类拓展BufferedReader的功能, 增强readLine方法返回 的字符串带有双引号+ 行号。
需求7: 编写一个类拓展BufferedReader的功能, 增强readLine方法返回 的字符串带有行号+ 分号+双引号。
class BufferedLineNum extends BufferedReader{
//行号
int count = 1 ;
public BufferedLineNum(Reader in) {
super(in);
}
@Override
public String readLine() throws IOException {
String line = super.readLine();
if(line ==null){
return null;
}
line = count+" "+ line;
count++;
return line;
}
}
//带分号的缓冲输入字符流
class BufferedSemi extends BufferedReader{
public BufferedSemi(Reader in) {
super(in);
}
@Override
public String readLine() throws IOException {
String line = super.readLine();
if(line==null){
return null;
}
line = line+";";
return line;
}
}
//带双引号的缓冲输入字符流
class BufferedQuto extends BufferedReader{
public BufferedQuto(Reader in) {
super(in);
}
@Override
public String readLine() throws IOException {
String line = super.readLine();
if(line==null){
return null;
}
line = "\""+line+"\"";
return line;
}
}
class Demo1 {
public static void main(String[] args) throws IOException {
File file = new File("/Users/alex/Downloads/img/a.txt");
//建立数据的输入通道
FileReader fileReader = new FileReader(file);
//建立带行号的缓冲输入字符流
BufferedLineNum bufferedLineNum = new BufferedLineNum(fileReader);
//带有分号的缓冲输入字符流
BufferedSemi bufferedSemi = new BufferedSemi(fileReader);
//带有双引号的缓冲输入字符流
BufferedQuto bufferedQuto = new BufferedQuto(fileReader);
String line = null;
while((line = bufferedQuto.readLine())!=null){
System.out.println(line);
}
}
}
练习:
一家三口每个人都会工作,儿子的工作就是画画,母亲的工作就是在儿子的基础上做一个增强,不单止可以画画,还可以上涂料。爸爸的工作就是在妈妈基础上做了增强,就是上画框。
public class Test {
public static void main(String[] args) throws IOException {
Person p = new Person();
S s = new S(p);
M m = new M(s);
F f = new F(m);
f.work();
}
}
class Person{
Person(){
}
void work() {
System.out.println("工作。。。。");
}
}
class S extends Person{
Person p;
public S(Person p) {
this.p = p;
}
@Override
void work() {
this.p.work();
System.out.println("画画");
}
}
class M extends Person{
Person p;
public M(Person p) {
this.p = p;
}
@Override
void work() {
this.p.work();
System.out.println("上颜色");
}
}
class F extends Person{
Person p;
public F(Person p) {
this.p = p;
}
@Override
void work() {
this.p.work();
System.out.println("做相框");
}
}