IO流高级

IO高级

缓冲流

简介:给普通的IO流套上一个缓冲区,所有的使用缓冲流进行的读写操作都是和缓冲区进行交互的,避免了频繁的IO操作,这样一来,带来的好处就是可以提高读写的效率,这个缓冲区实质上是一个数组。

缓冲流的作用:

为了提高读写的能力,本身没有读写的能力,要想进行读写就必须借助字符流/字节流实现,可以将缓冲流类比于催化剂或者高速的小车

常见的缓冲流:

BufferedInputStream:缓冲字节输入流

BufferedOutputStream:缓冲字节输出流

BufferedReader:缓冲字符输入流

BufferedWriter:缓冲字符输出流

字符流和缓冲字符流对比:

FileWriterBufferedWriter
有写的能力没有写的能力
FileWriter(){}public BufferWriter(Writer writer){this.writer = writer;}
write()write(){//1.实现写 writer.write(); //2.提高效率的代码 }
write(数组)
write(字符串)
close()close(){//1.将写出流关闭并刷新 writer.close() //2.将自己关闭}

使用缓冲流实现读写的步骤与字符流一样,只需要我们先通过构造方法传入一个字符流对象,同时缓冲流可以提高读写效率

总结:大家在使用流读写数据时,尽量使用缓冲流,缓冲流中尽量使用缓冲字符流,在字符缓冲流中比缓冲字节流中多了readLine()和newLine()方法

缓冲字节流
package bk.javase.p604.IO.Buffer;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/*
BufferedInputStream使用
 */
public class TestBufferedInputStream {
    public static void main(String[] args){
        /*
        过程与InputStream一模一样的
        缓冲字节输入流是需要基于一个字节输入流来进行实例化的
        在这里,BufferedInputStream构造方法中的InputStream对象,只是用来做当前的对象的实例化,在使用结束的时候,理论上来讲是需要关闭的
        实际上使用结束之后,只需要关闭BufferedInputStream即可
        */
        try( BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("C:\\TestIO\\from\\hello.txt"))) {
            //1.实例化一个字节数组
            byte[] array = new byte[1024];
            //2.声明一个整型变量,用来记录每次读取到了多少个字节数据
            int length = 0;
            //3.循环读取
            while((length = bufferedInputStream.read(array))!= -1){
                //4.将读取到的数据转成字符串输出到控制台
                String message = new String(array,0,length);
                System.out.println(message);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}
package bk.javase.p604.IO.Buffer;

import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class TestBufferedOutputStream {
    public static void main(String[] args){
        //1.实例化一个缓冲字节输出流对象
        try(BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("C:\\TestIO\\from\\hello.txt"))){
            //2.将数据写到输出流中
            bufferedOutputStream.write("hello,world,hello,everyone".getBytes());
            bufferedOutputStream.flush();
        } catch(FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

缓冲字符流

package bk.javase.p604.IO.Buffer;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class TestBufferedWriter {
    public static void main(String[] args){
        //1.借助一个字符输出流,实例化一个缓冲字符输出流对象
        try(BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("C:\\TestIO\\from\\hello.txt"))){
            bufferedWriter.write("王者荣耀是真的好玩,都给我上号");
            bufferedWriter.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

package bk.javase.p604.IO.Buffer;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class TestBufferedReader {
    public static void main(String[] args){
        //借助一个字符输入流,实例化一个缓冲字符输入流
        try(BufferedReader bufferedReader = new BufferedReader(new FileReader("C:\\TestIO\\from\\hello.txt"))) {
            //从流中读取数据
            char[] array = new char[100];
            int length = 0;
            while((length = bufferedReader.read(array)) != -1){
                System.out.println(new String(array,0,length));
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
缓冲字符流中的特殊方法:

BufferedReader类中多了一个方法readLine()

意义:读取缓冲流中的一行数据,可以逐行读取,一直到读到的数据为null,表示数据读完了,没有下一行数据了

注意事项:readLine()是逐行读取,但是,只能读到一行中的内容,并不能读取换行符

package bk.javase.p604.IO.Buffer;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderSpecial {
    public static void main(String[] args){
        try(BufferedReader reader = new BufferedReader(new FileReader("C:\\TestIO\\from\\hello.txt"))) {
            //1.定义一个字符串,用来接收每行读取到的数据(形如length)
            String line = "";
            //2.循环读取数据
            while((line = reader.readLine()) != null){
                //3.将读取到的数据输出
                System.out.println(line);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } ;
    }
}

BufferedWriter类中多了一个newLine()

1.写换行符,不同的系统中使用的默认换行符不一样,window系统 \r\n Linux系统 \n

2.意义:无参的方法,写一个换行符,支持跨平台(平台无关性)

package bk.javase.p604.IO.Buffer;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedWriterSpecial {
    public static void main(String[] args){
        try(BufferedWriter bufferWriter = new BufferedWriter(new FileWriter("C:\\TestIO\\from\\hello.txt"))) {
            bufferWriter.write("王者荣耀");
            bufferWriter.newLine();
            bufferWriter.write("是真的");
            bufferWriter.newLine();
            bufferWriter.write("好玩");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

LineNumberReader:

是BufferedReader的子类,不能读,但是可以提高效率,特有功能;设置行号,获取行号

设计模式简介:

设计模式是前人总结出来的对一些常见问题的解决方案,后人直拿来使用。常见的设计模式:单例,工厂,代理,适配器,装饰,适配器,装饰,模板,观察者等,一共有23种

装饰设计模式:

基于已经实现的功能,提供增强的功能

装饰设计模式的特点:

1.装饰设计模式的由来就来自于缓冲流的实现

2.从缓冲流的角度分析:使流原来的继承体更加简单;提高了效率;由于是在原有的基础上提高增强的功能,所	以他还属于原来的体系

Scanner

简介:

这个类,并不是一个IO流。而是一个扫描器,这个类最主要的作用,是从一个文件中或者一个流中浏览数据,在这个类中封装了若干个方法,方便了数据的读取

API:
方法描述
next()读取一个单词,遇到空格或者换行符就不再读取了
hasNext()判断是否还有下一个单词可以读取
nextLine()读取一行内容,遇到换行符就不再读取了
hasNextLine()判断是否还有下一行可以读取

注意事项:

这里的nextLine()和BufferedReader中的readLine()都可以读取一行数据,但是区别条件在于:结束条件不同

1.BufferedReader:如果读取到的数据时null,说明没有下一行数据了

2.Scanner:如果没有下一行了,再去读取,会出现异常,所以,此时的结束条件是hasNextLine()为false

package bk.javase.p604.IO.Buffer;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

public class TestScanner {
    public static void main(String[] args){
        //其实,Scanner在使用结束之后,也是需要进行关闭的,调用close()方法
        try(Scanner scanner = new Scanner(new File("C:\\TestIO\\from\\hello.txt"))){
            //读取文件中的内容
            while(scanner.hasNextLine()){
                System.out.println(scanner.nextLine());
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}
标准输入输出流:

简介:

标准输入流:System.in:“标准”输入流。此流已打开并准备提供输入数据。通常对应于键盘输入或者由主机环境或用户指定的另一个输入源

package bk.javase.p604.IO.Buffer;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;

/*
标准输出流
 */
public class TestSystem {
    public static void main(String[] args) {
//        //创建了标准输入流并关联了键盘(默认的)
//        InputStream inputStream = System.in;
//        //阻塞式方法
//        int num = 0;
//        try {
//            num = inputStream.read();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//        System.out.println(num);
//    }
        try(BufferedInputStream bufferedInputStream = new BufferedInputStream(System.in)){
            byte[] array = new byte[128];
            int length = 0;
            while((length = bufferedInputStream.read(array)) != -1){
                String str = new String(array,0,length);
                System.out.println(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
输入源:可以发送数据到内存的设备
输出源:可以接收内存的数据的设备
1.当前的流已经打开并关联了输入源-键盘
2.是一个字节流
3.如果不想让键盘充当输入源,可以通过setIn进行更换

标准输入流:System.out:标准输出流,此流已经打开并准备接受输出数据。通常,此流对应于显示器输出,或者由主机环境或用户指定的另一个输出目标

package bk.javase.p604.IO.Buffer;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;

/*
标准输出流
 */
public class TestSystemOut {
    public static void main(String[] args){
        PrintStream original = System.out;
        //PrintStream:是一个打印,可以将数据输出到指定位置
        try(PrintStream ps = new PrintStream(new FileOutputStream("C:\\TestIO\\from\\hello.txt",true))){
            //此时输出流会将内容打印到C:\TestIO\from\hello.txt中
//            ps.println("helloWorld");
            System.setOut(ps);
            //原本按照经验来说,System.out.println()会将内容打印到控制台
            //但是因为我重新设置了标准输出流,所以内容没被打赢到控制台而是指定的位置
            System.out.println("123");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }finally{
            System.setOut(original);
        }
        System.out.println("你好");
        //System.out  标准输出流地址,将内容输出到控制台
    }
}
转换流:

使用转换流的作用:在进行文件读取的时候,如果项目采用的字符集和文件的字符集不同,会出先乱码的情况下,但使用转换流可以解决这个问题

//使用方法类似于缓冲流
//转换输入流:可以以指定的字符集读取某一个文件中的数据
//转换输出流:可以以指定的字符集把数据写入到某一个文件
InputStreamReader reader = new InputStreamReader(new FileInputStream(),"GBK");
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(),"GBK");
打印流

简介:除了拥有输出流的特点之外,还有打印的功能

字节打印流:PrintStream

字符打印流:PrintWriter

字节打印流:
字节打印流支持的设备:
File类型的文件
字符串类型的文件
字节输出流
package bk.javase.p604.IO.Buffer;

import java.io.*;

public class TestPrintStream {
    public static void main(String[] args){
        /*
        字节打印流支持的设备
         */
//        //1.File类型的文件
//        PrintStream p1 = new PrintStream(new File("C:\\TestIO\\from\\hello.txt"));
//        //2.字节输出流
//        PrintStream p2 = new PrintStream(new FileOutputStream("C:\\TestIO\\from\\hello.txt"));
//        //3.字符串类型的文件
//        PrintStream p3 = new PrintStream("C:\\TestIO\\from\\hello.txt");

        //实例
        try {
            PrintStream p1 = new PrintStream(new File("C:\\TestIO\\from\\hello.txt"));
            //直接使用write方法打印,默认只支持一个字节,所以当数据超出了一个字节的范围,会出现以下错误
//            p1.write(97);//00000000 01100001----->a
//            p1.write(353);//00000001 01100001---->a   默认直接删掉八位之外的所有数据
            //所以为了避免出现这样的问题,我们不直接使用write()方法,而是使用print()方法
           p1.print(353);

            //此时展示一下print方法的内部实现原理
            //先将353转成字符串再转成字节数组
            p1.write(String.valueOf(353).getBytes());
            p1.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
字符打印流:
字符打印流支持的设备:
File类型的文件
字符串类型的文件
字节输出流
字符写入流
package bk.javase.p604.IO.Buffer;

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class TestPrintWriter {
    public static void main(String[] args) {
        PrintWriter pw;

        {
            try {
                pw = new PrintWriter(new FileWriter("C:\\TestIO\\from\\hello.txt"));
                pw.write("bingbing");
                pw.close();

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

注意点:

public PrintWriter(Writer out,boolean autoFlush){}

autoFlush-boolean变量:如果为true,则println,printf或format方法将自动刷新输出缓冲区,但是执行print()方式时需要手动刷新

编码问题:

常用的字符集:
中国的字符集:GBK/GB2312
欧洲的:ISO8859-1
通用的:UTF-8
美国的:ASCII

对中文的处理:

GBK:2个字节,ISO8859-1:1个字节,UTF-8:3个字节,Unicode:2个字节

说明:GBK,UTF-8支持中文,ISO8859-1不支持中文

编码:将字符串转化成byte序列的过程

解码:将byte序列转成字符串的过程

编码错误(乱码):乱码,在执行读写的时候,由于使用的字符集不同,会出现编码的错误

解决办法:先编码再解码

序列化流:

简介:

将短期存储的数据实现长期存储,这个过程对应的流的就是序列化流

数据的存储分成两类:

1.短期存储:存放到内存里,随着程序的关闭而释放----对象,集合,数组,变量

2.长期存储:存储在磁盘中,即使程序关闭了,数据仍然存在—文件

序列化:将数据从内存放到磁盘,可以实现数据的长久保存

反序列化:将数据从磁盘放回到内存

注意事项:

ObjectInputStream,ObjectOutpurStream,主要是用来做对象的序列化和反序列化

序列化和反序列化是对象的持久化存储的一种常用手段

所有的要序列化到本地的对象,类必须实现java.io.Serilizable接口

实现Serilizable接口的类可以达到的目的
1.可以进行序列化
2.进行序列化的类的元素必须支持可序列化
3.可序列化类的所有子类型本身都是可序列化的
4.接口本省没有方法或者字段,只是用来表示可序列化的语义

如果需要序列化多个文件到本地,尽量不要序列化到一个文件中,如果需要序列化多个文件到本地,通常采用的方式,是存集合,将多个对象存入到一个集合中,将这个集合序列化到本地

Properties

简介:

properties不是一个IO流,而是一个集合,是HashTable的子类

使Properties主要是为了描述程序中的属性列表文件,有时候,我们会将一些比较简单的项目配置信息,以.properties格式的文件进行存储,可以使用Propeprties对象读写.properties文件

注意:

因为存储的是属性,属性本身就是以键值对的方式存储,这里的键和值都必须是字符串,所以不需要考虑泛型

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值