IO流知识点大全

IO流

IO流概述:

  • 将文件从C盘剪切到D盘这种操作,可以将这种数据传输操作,看作一种数据的流动,
    按流动的方向分为:输入Input和输出Output,对于D盘就是输入,对于C盘就是输出

  • java中的IO操作主要是指的是 java.io包下的一些常用类的使用,通过这些常用类对数据的读取(输入Input)和 写出(输出Output)

  • 输入就是文件中的数据输入到程序中,输出就是程序中的数据输出到文本中

IO流的分类:

  • 按照流的方向来分,可以分为:输入流和输出流
  • 按照流动的数据类型来分,可以分为:字节流和字符流

字节流:

  • 输入流: InputStream
  • 输出流: OutputStream

字符流:

  • 输入流: Reader
  • 输出流:Writer

OutputStream

此类定义:

  • public abstract class OutputStream
    extends Object
    implements Closeable, Flushable
    
  • 此抽象类是表示输出字节流的所有类的超类。输出流接受输出字节并将它们发送到某个接收器。

    需要定义OutputStream的子类的应用程序必须始终至少提供一个写入一个输出字节的方法。

方法:

在这里插入图片描述

write(int b)此方法 只能写入 int 的低八位(最后的8个bit)

注意: 使用流的时候一定要 close!

FileOutputStream

  • public class FileOutputStream
    extends OutputStream
    
  • 文件输出流是用于将数据写入FileFileDescriptor的输出流。

构造方法:
在这里插入图片描述

boolean append 意思是 是否继续追加(在之前的文件后面接着写还是删除内容后再写)。

方法与Output Stream方法一样。

demo:

public class OutputStreamDemo {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("e:/demo/a.txt", true);
        byte[] bytes = {65,66,67,68,69};
        String str = "hello,IO";
        fos.write(bytes);
        fos.write(str.getBytes(StandardCharsets.UTF_8) , 1,3);
        fos.close();
    }
}

结果:

在这里插入图片描述

InputStream

定义:

  • public abstract class InputStream
    extends Object
    implements Closeable
    
  • 此抽象类是表示输入字节流的所有类的超类(顶级父类)

常用方法:如下

close

void close() ; ——关闭流

read

在这里插入图片描述

public abstract int read() throws IOException

描述:从输入流中读取下一个数据字节。 值字节返回int ,范围为0至255 。 如果由于到达流末尾而没有可用字节,则返回值-1 。

结果:数据的下一个字节,如果到达流的末尾, -1 。
public int read(byte[] b) throws IOException

描述:从输入流中读取一些字节数并将它们存储到缓冲区数组b 。 实际读取的字节数以整数形式返回。

如果b的长度为零,则不读取任何字节,并返回0 ; 否则,尝试读取至少一个字节。 如果由于流位于文件末尾而没有可用字节,则返回值-1 ; 否则,至少读取一个字节并存储到b 。
读取的第一个字节存储在元素b[0] ,下一个字节存入b[1] ,依此类推。 读取的字节数最多等于b的长度。 设k为实际读取的字节数; 这些字节将存储在元素b[0]到b[ k -1] ,使元素b[ k ]到b[b.length-1]不受影响。 

结果:读入缓冲区的总字节数,如果由于已到达流末尾而没有更多数据, -1 
public int read(byte[] b, int off, int len) throws IOException

b - 读取数据的缓冲区。 
off - 数据写入的数组 b中的起始偏移量。 
len - 要读取的最大字节数。

效果与 int read(byte[] b) 一样
    

子类FileInputStream

read读取:

public class InputStream {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("e://demo//a.txt");
        byte b = 0;
        while(true) {
            b = (byte) fis.read();
            if (b == -1) break;
            System.out.println((char) b);
        }
        fis.close();
    }
}

结果:

A
B
C
D
E
e
l
l

read(byte[] b) 读取数据

public class InputStream {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("e://demo//a.txt");
        // 文件内容:abcdefghigklmnopqrstuvwxyz
        byte[] b = new byte[10];
        fis.read(b); // 每次读十个
        System.out.println(new String(b)); //abcdefghig
        fis.read(b); // 每次读十个
        System.out.println(new String(b)); //klmnopqrst
        fis.read(b); // 每次读十个
        System.out.println(new String(b)); //uvwxyzqrst
        fis.close();
    }
}
读取出现问题!!! 原因是最后只有六个字母 只是覆盖了byte[]前六位 后面四位没有被覆盖,出现了现象!

解决办法:

public class InputStream {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("e://demo//a.txt");
        // 文件内容:abcdefghigklmnopqrstuvwxyz
        byte[] b = new byte[10];
        int len = fis.read(b);// 每次读十个
        System.out.println(new String(b,0,len)); //abcdefghig
        len = fis.read(b); // 每次读十个
        System.out.println(new String(b,0,len)); //klmnopqrst
        len = fis.read(b); // 每次读6个
        System.out.println(new String(b,0,len)); //uvwxyz
        len = fis.read(b); // len = -1
        fis.close();
    }
}

用字节流读取文字的时候会出现乱码问题

在这里插入图片描述

原因: 用字节流读取文字时,因为汉字的编码规则 不知道使用几个字节编成一个汉字,所有用byte[10] 读取的时候会出现这样的 只读取到 汉字的一半 然后会出现乱码 解决办法:使用Reader流读取!

Writer

该类是字符输入流的顶级父类,是个抽象类

定义:

  • public abstract class Writer
    extends Object
    implements Appendable, Closeable, Flushable
    

子类:

已知直接子类: 
BufferedWriterCharArrayWriterFilterWriterOutputStreamWriterPipedWriterPrintWriterStringWriter 

常用方法:

变量和类型方法描述
Writerappend(char c)将指定的字符追加到此writer。
Writerappend(CharSequence csq)将指定的字符序列追加到此writer。
Writerappend(CharSequence csq, int start, int end)将指定字符序列的子序列追加到此writer。
abstract voidclose()关闭流,先冲洗它。
abstract voidflush()刷新流。因为有缓存,所以要刷新。
voidwrite(char[] cbuf)写一个字符数组。
voidwrite(String str)写一个字符串

FileWriter子类

定义:

  • public class FileWriter
    extends OutputStreamWriter
    

该类继承了OutputStreamWriter

构造方法:

构造器描述
FileWriter(File file)File写一个 FileWriter ,使用平台的 [default charset] (默认字符集)
FileWriter(File file, boolean append)在给出要写入的 FileWriter下构造 File ,并使用平台的 [default charset构造]一个布尔值,指示是否附加写入的数据。
FileWriter(File file, Charset charset, boolean append)构造FileWriter给出File写入,charset和一个布尔值,指示是否附加写入的数据。

demo:

public class Write {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("e://demo//a.txt");
        char[] b = new char[10];
        fw.write("锄禾日当午,汗滴禾下土!");
        fw.append("谁知盘中餐,").append("粒粒皆辛苦!");
        fw.close();
    }
}

在这里插入图片描述

Reader

定义:

  • public abstract class Reader
    extends Object
    implements Readable, Closeable
    
  • 用于读取字符流的抽象类,字符流的顶级父类

常用方法:

变量和类型方法描述
abstract voidclose()关闭流并释放与其关联的所有系统资源。
intread()读一个字符。读取不到返回-1
intread(char[] cbuf)将字符读入数组,返回读取长度

FileReader

定义:

  • public class FileReader
    extends InputStreamReader
    
  • 使用默认缓冲区大小从字符文件中读取文本。继承了InputStreamReader

构造器:
在这里插入图片描述

demo:

public class Reader {
    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("e://demo//a.txt");
        char[] chars = new char[10];
        while(true){
            int len = fr.read(chars);
            if (len == -1)
                break;
            //System.out.println(new String(chars));这句输出有问题
            System.out.println(new String(chars,0,len));
        }
        fr.close();
    }
}

运行结果:

锄禾日当午,汗滴禾下
土!谁知盘中餐,粒粒
皆辛苦!

Flush刷新管道

一般使用字符流读取内容时,将一个个字符存储到缓存区 ,所以一般要刷新flush

将缓冲区的内容写入文件。

使用close方法也能刷新缓冲区。

字节流 "装饰"为 字符流

字节流转换成字符流 --> 使用了装饰者模式

使用 InputStreamReader构造方法进行转换

在这里插入图片描述

参数1 : 要转换的字节流
参数2 : 指定编码名称

demo:

public class Reader {
    public static void main(String[] args) throws IOException {
        // 定义个 字节流
        FileInputStream fis = new FileInputStream("e://demo//a.txt");

        // 将字节流转换成字符流
        InputStreamReader fr = new InputStreamReader(fis);
        char[] chars = new char[10];
        while(true){
            int len = fr.read(chars);
            if (len == -1)
                break;
            System.out.println(new String(chars,0,len));
        }
        fr.close();
    }
}

PrintStream

定义:

在这里插入图片描述

  • public class PrintStream
    extends FilterOutputStream
    implements Appendable, Closeable
    
  • PrintStream向另一个输出流添加功能,即能够方便地打印各种数据值的表示。

  • 与其他输出流不同,PrintStream永远不会抛出IOException异常;相反,异常情况仅设置可通过checkError方法测试的内部标志

  • 还可以指定是否自动flush

方法:该类方法与Out的方法几乎一样

在这里插入图片描述

demo:

public static void main(String[] args) throws IOException {
    // 字节打印流
    PrintStream ps = new PrintStream("e://demo//a.txt");
    ps.println("11111");
    ps.println("22222");
    ps.println("33333");
    ps.println("44444");
    ps.println("55555");
    ps.flush();
    ps.close();
    // 字符打印流
    PrintWriter pw = new PrintWriter("e://demo//a.txt");
    pw.println("pw11111");
    pw.println("pw22222");
    pw.println("pw33333");
    pw.println("pw44444");
    pw.println("pw55555");
    pw.flush();
    pw.close();
}

BufferedReader

缓存读取流,将字符输入流 转换为带有缓存 可以一次读取一行的缓存字符读取流

新增方法:

public String readLine() throws IOException

  	描述: 读一行文字。 一行被认为是由换行符('\ n'),回车符('\ r'),回车符后紧跟换行符或到达文件结尾的任何一个终止(EOF)。
    结果:	包含行内容的字符串,不包括任何行终止字符;如果在未读取任何字符的情况下到达流末尾,则返回null
    

demo:

public static void main(String[] args) throws IOException {
    // 字符输出流
    FileReader fr = new FileReader("e://demo//a.txt");
    // 转换成bufferedReader
    BufferedReader bfd = new BufferedReader(fr);
    String str ;
    while( (str = bfd.readLine()) != null){
        System.out.println(str);
    }
    fr.close();
}

收集异常日志

可以利用IO流将错误异常信息写入文件,可以已日期创建文件,将每天的异常加入到文件中

demo:

 public static void main(String[] args) throws IOException {
        String str = null;
        // 创建printWriter流
        PrintWriter pw = new PrintWriter("e://demo//bug.txt");
        try{
            // 这句代码 会产生空指针异常
            str.equals("hello");
        } catch (Exception e){
            //加入时间
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm ss");
            String format = sdf.format(new Date());
            pw.println(format);
            // 将异常写入文件
            e.printStackTrace(pw);
            pw.flush();
        }
 }

运行结果:

在这里插入图片描述

properties

定义:

  • public class Properties
    extends Hashtable<Object,Object> 
    
  • 继承 Hashtable

  • Properties类表示一组持久的属性。 Properties可以保存到流中或从流中加载。 属性列表中的每个键及其对应的值都是一个字符串。

存数据demo:

public static void main(String[] args) throws IOException {

    Properties ppt = new Properties();
    ppt.put("name","金苹果");
    ppt.put("info","讲述了苹果种植的过程");
    // 创建字符流
    FileWriter fw = new FileWriter("e://demo//info.properties");
    ppt.store(fw,"存储的图书");
    fw.close();
}

结果:

在这里插入图片描述

取数据demo:

public static void main(String[] args) throws IOException {

    /* Properties ppt = new Properties();
        ppt.put("name","金苹果");
        ppt.put("info","讲述了苹果种植的过程");
        // 创建字符流
        FileWriter fw = new FileWriter("e://demo//info.properties");
        ppt.store(fw,"存储的图书");
        fw.close();*/

    Properties ppt = new Properties();
    // 创建 字符输入流
    FileReader fr = new FileReader("e://demo//info.properties");
    ppt.load(fr);
    String name = ppt.getProperty("name");
    String info = ppt.getProperty("info");
    System.out.println(name);
    System.out.println(info);
}

结果:

金苹果
讲述了苹果种植的过程

序列化 与 反序列化

序列化:将程序中的对象 存储到 文件中的过程

反序列化: 将文件的内容 转化为 程序中的对象 的过程

序列化:

java官方考虑到有些类不想被序列化,所以就加了个标识 需要被序列化的类继承Serializable接口 (该接口没有任何方法)

对象的属性也必须全部继承serializable接口。

在这里插入图片描述

demo:

public static void main(String[] args) throws IOException {

    //序列化:
    Book book = new Book("java","从入门到入土");
    // 字节输出流
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("e://demo//a.text"));
    oos.writeObject(book);
    oos.close();

    // 反序列化
}

static class Book implements Serializable{
    private String name;
    private String info;

    public Book() {
    }

    public Book(String name, String info) {
        this.name = name;
        this.info = info;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    @Override
    public String toString() {
        return "Book{" +
            "name='" + name + '\'' +
            ", info='" + info + '\'' +
            '}';
    }
}

结果:

在这里插入图片描述

反序列化:

demo:

public static void main(String[] args) throws IOException, ClassNotFoundException {

    // 反序列化
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream("e://demo//a.text"));
    Book book = (Book) ois.readObject();
    System.out.println(book);
}

static class Book implements Serializable{
    private String name;
    private String info;

    public Book() {
    }

    public Book(String name, String info) {
        this.name = name;
        this.info = info;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    @Override
    public String toString() {
        return "Book{" +
            "name='" + name + '\'' +
            ", info='" + info + '\'' +
            '}';
    }
}

运行结果:

Book{name='java', info='从入门到入土'}

try-with-resources

在jdk1.7之前,当我们对一些流进行关闭时进行的处理:

public static void main(String[] args) {
    FileReader fr = null ;
    try{
        fr = new FileReader("e://demo//a.text");
        // 读取一个字符操作
        int ch = fr.read();
        System.out.println((char) ch);

    } catch (IOException e){
        e.printStackTrace();
    } finally {
        // 关闭流 当关闭流放入try里面时 当读取字符出错时,fr.close() 就会执行不了
        // 只能放这里
        // 放到这里又要处理异常
        try{
            fr.close();
        } catch (Exception e){
            // 当 第10行代码 fr 没有被赋值成功 可能还会报 NullPointException
            // 只能用 放大到 Exception 处理
            e.printStackTrace();
        }
    }
}

在jdk1.7时,使用如下try() 括号里面实现资源声明时 必须要实现 因为close方法必须会被自动调用

Closeable 或 AutoCloseable 这两个接口

demo:

public static void main(String[] args) {

    try(FileReader fr = new FileReader("e://demo//a.txt");){
        // 读取一个字符操作
        int ch = fr.read();
        System.out.println((char) ch);
    } catch (IOException e){
        e.printStackTrace();
    }
}

这里也有不好的地方,当我 fr 对象 还需要使用 ,不想再这就被关闭,怎么办?

这时 jdk9 版本进行了优化

FileReader fr = new FileReader("e://demo//a.txt");
PrintWriter fw = new PrintWriter("e://demo//a.txt");
try(fr,fw){
    // 读取一个字符操作
    int ch = fr.read();
    System.out.println((char) ch);
} catch (IOException e){
    e.printStackTrace();
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值