java基础-io流

一、FIle类

概念:代表物理盘符中的一个文件或者文件夹

常用方法:

FileFilter接口

FileFilter:文件过滤器接口

boolean accept(File pathname):当调用File乐熊的listFiles()方法时,支持传入FileFilter过滤接口实现类,对获取文件进行过滤,只有满足条件的文件才可出现在listFilters()的返回值中。

public void testio(File file){
    File[] files = file.listFiles(new FileFilter() {
        @Override
        public boolean accept(File pathname) {
            //过滤的条件 实现的功能
            return false;
        }
    });
}

 二、什么是io

生活场景:编辑一个文本文件,忘记ctrl+s,可能文件就白白编辑,当你电脑上插入一个U盘,可以拷贝视频、文件到电脑的硬盘中,那么数据都是在哪些设备上?键盘,内存,外接设备等等。

我们把数据的传输,可以看成是数据的流动,根据流动的方向,以内存为基准,分为输入input和输出output,即流向内存是输入流,流出内存是输出流。java中I/O操作主要是指使用java.io包下的内容,进行输入、输出操作。输入也称读取数据输出也称写出数据

三、IO分类

数据的流向分为输入流和输出流。

输入流:把数据从其他设备上读取到内存中的流。

输出流:把数据从内存中写出到其他设备上的流。

根据数据的类型分为:字节流和字符流。

字节流:以字节为单位,读写数据的流。

字符流:以字符为单位,读写数据的流。

        输入流       输出流
字节流                     字节输入流InputStream字节输出流OutputStream
字符流       字符输入流Reader字符输出流Writer

四、字节流

一切皆为字节

一切文件数据(文本、图片、视频等)在存储是,都是以二进制数字的形式保存,是一个一个的字节,那么传输时一样如此。所以,字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据。

字节输出流

java.io.OutputStream抽象列是标识字节输出流的所有类的超类,将指定的字节信息写出到目的地。它定义了字节输出流的基本共性功能方法。

  • public void close():关闭此输出流并释放与此流相关联的任何系统资源。
  • public void flush():刷新此输出流并强制任何缓冲的输出字节被写出。
  • public void write(byte b[]):将b.length字节从指定的字节数组写入此输出流。
  • public void write(byte b[], int off, int len):从指定的字节数组写入len字节,从偏移量off开始输出到此输出流。
  • public abstract void write(int b):将指定的字节输出流。

FileOutputStream类

构造方法:

  • public FileOutputStream(File file):创建文件输出流以写入由指定的File对象表示的文件。
  • public FileOutputStream(String name):创建文件输出流以指定的名字写入文件。

1、写出字节:write(int b)方法,每次可以写出一个字节数据

2、写出字节数组:write(byte[] b),每次可以写出数组中的数据

3、写出指定长度字节数组:write(byte[] b,int off,int len),每次写出从off索引开始,len个字节

字节输入流

java.io.InputStream抽象类是表示字节输入流的所有类的超类,可以读取字节信息到内存中,他定义了字节输入流的基本共性功能方法。

  • public void close():关闭此输入流并释放与此相关联的任何系统资源。
  • public abstract int read():从输入流读取数据的下一个字节。
  • public int read(byte[] b):从输入流中读取一些字节数,并将他们存储到字节数组b中。

FileInputStream类

构造方法:

  • public FileInputStream(File file):通过打开与实际文件的连接来创建一个FileInputStream,该文件由文件系统中的File对象file命名。
  • public FileInputStream(String name):通过打开与实际文件的连接来创建一个FileInputStream,该文件由文件系统中的路径名name命名。

1、读取字节:read()防范,每次可以读取一个字节的数据,提升为int类型,读取到文件末尾,返回-1。

2、使用字节数组读取:read(byte[] b),每次读取b的长度个字节到数组中,返回读取道德有效字节个数,读取到末尾时,返回-1。

五、字符流

字符输入流

java.io.Reader抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中,它定义了字符输入流的基本共性功能方法。

  • public void close():关闭此流并释放与此流相关的任何系统资源。
  • public int read():从输入流中读取一个字符。
  • public int read(char[] cbuf):从输入流中读取一些字符,并将他们存储到字符数组cbuf中。

FileReader类

构造方法

  • public FileReader(File file):创建一个新的FileReader,给定要读取的File对象。
  • public FileReader(String fileName):创建一个新的FileReader,给定要读取的文件的名称。

构造时要使用系统默认的字符编码和默认字节缓冲区

1.字符编码:字节与字符的对应规则,Windows系统的中文编码默认是GBK编码表。idea中UTF-8

2.字节缓冲区:一个字节数组,用来临时存储字节数据。

  • 1、读取字符:read防范,每次可以读取一个字符的数据,提升为int类型,读取到文件末尾,返回-1,循环读取。
  • 2、使用字符数组读取:read(char[] cbuf),每次读取b的长度个字符到数组中,返回读取到的有效字符个数,读取到末尾时,返回-1。

字符输出流

java.io.Writer抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地。它定义了字符输出流的基本共性功能方法。

  • public void write(int c):写入单个字符。
  • public void write(char cbuf[]):写入字符数组。
  • abstract public void write(char cbuf[], int off, int len):写入字符数组的某一部分,off数组的开始索引,len写入的字符个数。
  • public void write(String str):写入字符串。
  • public void write(String str, int off, int len):写入字符串的某一部分,off字符串的开始索引,len写的字符个数。
  • public void flush():刷新该流的缓冲。
  • public void close():关闭此流,但要先刷新它。

FileWriter类

  • public FileWriter(File file):创建一个新的FileWriter,给定要读取的File对象。
  • public FileWriter(String fileName):创建一个新的FileWriter,给定要读取的文件的名称。

构造时使用系统默认的字符编码和默认字节缓冲区:

  • 1、写出字符:writer(int b)方法,每次可以写出一个字符数据。
  • 2、写出字符数组:writer(char[] cbuf)和writer(char[] cbuf,int off,int len),每次可以写出字符数组中的数据,用法类似FileOutStream
  • 3、写出字符串:writer(String str)和writer(String str,int off,int len),每次可以写出字符串中的数据,更加方便。

因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中,但是关闭的流对象,是无法继续写出数据的。如果我们既想写出数据,又想继续使用流,就需要flush方法了。

 六、缓冲流

概述

缓冲流也叫高效流,是对4个基本的FileXXX流的增强,所以也是4个流,根据数据类型分类:

  • 字节缓冲流:BufferedInputStream,BufferedOutputStream
  • 字符缓冲流:BufferedReader,BufferedWriter

缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。

字节缓冲流

构造方法:

  • public BufferedInputStream(InputStream in):创建一个新的缓冲输入流
  • public BufferedOutputStream(OutputStream out):创建一个新的缓冲输出流

字符缓冲流

构造方法

  • public BufferedReader(Reader in):创建一个新的缓冲输入流。
  • public BufferedWriter(Writer out):创建一个新的缓冲输出流。

特有方法

字符缓冲流的基本方法与普通字符流调用方法一致

  • BuffedReader:public String readLine():读一行文字。
  • BufferedWriter:public void newLine():写一行行分隔符,由系统属性定义符号。

七、转换流

在idea中,使用FileReader读取项目中的文本文件。由于idea的设置,都是默认的UTF-8编码,所以没有任何问题,但是,当读取Windows系统中创建的文本文件时,由于Windows系统的默认是GBK编码,就会出现乱码。

那么如何解决这个问题?

InputStreamReader类

转换流java.io.InputStreamReader,是Reader的子类,是从字节流到字符流的桥梁。它读取字节,并使用指定的字符集将其解码为字符,他的字符集可以由名称指定,也可以接受平台的默认字符集。

  • public InputStreamReader(InputStream in):创建一个使用默认字符集的字符流。
  • public InputStreamReader(InputStream in, String charsetName):创建一个指定字符集的字符流。

八、序列化

概述

java提供了一种对象序列化的机制,用一个字节序列可以表示一个对象,该字节序列包含该对象的数据、对象的类型和对象中存储的属性等信息、字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息。

反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化。对象的数据、对象的类型和对象中存储的数据信息,都可以用来在内存中创建对象。

ObjectOutputStream类

java.io.ObjectOutputStream类,将java对象的原始数据类型写出到文件,实现对象的持久存储。

序列化操作

一个对象要想序列化,必须满足两个条件:

  • 必须实现serializable接口。
  • 必须保证其所有属性均可序列化。(transient修饰为临时属性,不参与序列化)

写出对象方法

public final void writeObject(Object obj):将指定的对象写出。


import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;

class Student implements Serializable {
        public String name;

        public String remark;

        public String getName() {
                return name;
                }

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

        public String getRemark() {
                return remark;
                }

        public void setRemark(String remark) {
                this.remark = remark;
                }

        public Student() {
                }

        public Student(String name, String remark) {
                this.name = name;
                this.remark = remark;
                }

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

}

public class SerDemo {
    public static void main(String[] args) throws IOException {
        ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("Student.txt"));
        Student student = new Student("zhangsan", "ceshi");
        outputStream.writeObject(student);
        outputStream.close();
    }


}

ObjectInputStream类

ObjectInputStream反序列化流,将之前使用ObjectOutputStream序列化的原始数据恢复为对象。

反序列化操作

如果能找到一个对象的class文件,我们就可以进行反序列化操作,调用ObjectInputStream读取对象的方法。

public final Object readObject():读取一个对象。

public class SerDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("Student.txt"));
        Student o = (Student) inputStream.readObject();
        System.out.println(o);
        inputStream.close();
    }
}

注意:

对于JVM可以反序列化,它必须是能够找到class文件的类。如果找不到该类的class文件,则抛出一个ClassNOTFoundException异常。

 当JVM反序列对象时,能找到class文件,但是class文件在学历恶化对象之后发生了修改,那么反序列化操作也会失败,抛出一个InvalidClassException异常。

发生这个异常的原因在于:该类的序列版本号与从流中读取的类描述符的版本不匹配,serialVersionUID该版本的目的在于验证序列化的对象和对应类是否版本匹配。

serialVersionUID是一个非常重要的字段,因为Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同则认为一致,可以进行反序列化,否则就会出现序列化版本不一致的异常。

一般来说,定义serialVersionUID的方式有两种:

1.采用默认的1L,具体为private static final long serialVersionUID= 1L;

2.在可兼容的前提下,可以保留旧版本号,如果不兼容,或者想让它不兼容,就手工递增版本号。

根据类名、接口名、成员方法以及属性等来生成一个64位的哈希字段,例如 private static final long serialVersionUID=XXXL;

这种方式适用于如下场景:

1.开发者认为每次修改类后就需要生成新的版本号,不想向下兼容,操作就是删除原有serialVersionUID声明语句,在自动生成一下。

2.能够保证每次更改类结构后改变版本号,但还是要手工去生成。

 九、Properties属性类

常用方法

  • public Object setProperty(String key, String value):保存一对属性。
  • public String getProperty(String key):使用此属性列表中指定的键搜索属性值。
  • public Set<String> stringPropertyNames():所有键的名称的集合。
  • public synchronized void load(InputStream inStream):从字节输入流中读取键值对。
 public static void main(String[] args) throws IOException, ClassNotFoundException {
        Properties properties = new Properties();
        properties.setProperty("a","a");
        properties.getProperty("a");
        properties.load(new FileInputStream("db.properties"));
        Set<String> strings = properties.stringPropertyNames();
        for (String string : strings) {
            String property = properties.getProperty(string);
            System.out.println(property);
        }

    }

小贴士:文本中的数据,必须是键值对形式,可以使用空格、等号、冒号等符号分隔。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值