Java教程

Java SE09_I/O框架

本文主要是介绍Java SE09_I/O框架,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

I/O 框架

1 流的概念

  内存与存储设备之间传输数据的通道,数据借助流传输。


2 流的分类

  按方向【重点】

  • 输入流:将<存储设备>中的内容读到<内存>中
  • 输出流:将<内存>中的内容写到<存储设备>中

  按单位

  • 字节流:以字节为单位,可以读写所有数据
  • 字符流:以字符为单位,只能读写文本数据

  按功能

  • 节点流:具有实际传输数据的读写功能
  • 过滤流:在节点流的基础之上增强功能

3 字节流

字节流的父类(抽象类)

//InputStream 字节输入流
public int read(){}
public int read(byte[] b){}
public int read(byte[] b, int off, int len){}

// OutputStream 字节输出流
public void write(int n){}
public void write(byte[] b){}
public void write(byte[] b, int off, int len){}

3.1 文件字节流

文件输入流代码演示:

    public static void main(String[] args) throws Exception {
        /*
             * 演示FileInputStream的使用
             * 文字字节输入流
             */
        //1.创建文件字节输出流并指定文件路径
        FileInputStream fis =new FileInputStream("E:\\newstart\\linshi\\aaa.txt");

        //2.读取文件
        //2.1单个字节的读取
        //        int data = 0;
        //        while((data = fis.read())!=-1){
        //            System.out.print((char)data);//abcdefg
        //        }
        //2.2一次读取多个字节
        //        byte[] buf = new byte[3];//大小为3的缓存区
        //        int count = fis.read(buf);//一次读3个
        //        System.out.println(new String(buf));//abc
        //        System.out.println(count);//3
        //2.2优化之后
        byte[] buf = new byte[3];//大小为3的缓存区
        int count = 0;
        while ((count = fis.read(buf)) != -1) {
            System.out.print(new String(buf, 0, count)+" ");//abc def g
        }
        System.out.println();

        //3.关闭
        fis.close();
    }

文件输出流代码演示:

    public static void main(String[] args) throws Exception {
        /*
        * 演示FileOutputStream的使用
        * 文字字节输出流
        */
        //1.创建文件字节输出流并指定文件路径,append=true时,可进行追加,不然会覆盖
        FileOutputStream fos =new FileOutputStream("E:\\newstart\\linshi\\bbb.txt",true);

        //2.写入文件
        //单个写入
        String str = "hello world";
        fos.write(str.getBytes());

        //3.关闭
        fos.close();
        System.out.println("执行完毕");
    }

3.2 文件复制案例

代码演示:

	public static void main(String[] args) throws Exception {
        //文件的复制
        //1.创建流
        //输入流
        FileInputStream fis = new FileInputStream("路径\\aaa.txt");
        //输出流
        FileOutputStream fos = new FileOutputStream("路径\\bbb.txt");
        //2.一边读一边写
        byte[] buf = new byte[1024];
        int count = 0;
        while((count = fis.read(buf)) != -1){
        fos.write(buf, 0, count);
        }
        //3.关闭
        fis.close();
        fos.close();
        System.out.println("copy完毕");
	}

3.3 字节缓冲流

缓冲流:BufferedInputStream/ BufferedOutputStream

  • 提高IO效率,减少访问磁盘次数
  • 数据存储在缓冲区中,flush是将缓冲区的内容写入文件中,也可以直接close

代码演示:

public static void main(String[] args) throws Exception {
        /**
         * 使用字节缓冲流读取
         * BufferedInputStream
         */
        //1.创建BufferedInputStream
        FileInputStream fis = new FileInputStream("E:\\newstart\\linshi\\aaa.txt");
        BufferedInputStream bis = new BufferedInputStream(fis);
        //2.读取
        //方法1(推荐)
//        int data = 0;
//        while ((data = bis.read()) != -1){
//            System.out.print((char)data);
//        }
        //方法2
        byte[] buf = new byte[1024];
        int count = 0;
        while((count = bis.read(buf)) != -1){
            System.out.println(new String(buf,0, count));
        }
        //3.关闭
        bis.close();
    }

代码演示:

    public static void main(String[] args) throws Exception {
        /**
         * 使用字节缓冲流写入数据
         * BufferedOutputStream
         */
        //1.创建字节输出缓冲流
        FileOutputStream fos =new FileOutputStream("E:\\newstart\\linshi\\bbb.txt");
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        //2.写入文件
        for (int i = 0; i < 10; i++) {
            bos.write("helloword\r\n".getBytes());//写入8k缓冲区
            bos.flush(); // 刷新到硬盘 如果不flush(),关闭流之后也可以显示,但是刷新可以防止数据丢失
        }
        //3.关闭(内部调用flush方法)
        bos.close();
    }

4 对象流

ObjectOutputStream / ObjectInputStream

  • 增强了缓冲区功能
  • 增强了读写8种基本数据类型和字符串的功能
  • 增强了读写对象的功能
    • readObject() 从流中读取一个对象
    • writeObject(Object obj) 向流中写入一个对象

使用流传输对象的过程称为序列化、反序列化

理解:从内存写入文件到硬盘的过程称之为序列化,反之为反序列化。

4.1 序列化

代码演示:

	public static void main(String[] args) throws Exception {
        /**
         * 使用ObjectOutputStream实现对象的序列化
         * 要求:序列化的类必须实现Serializable接口,标记为可序列化的状态
         */
        //1.创建对象流
        FileOutputStream fos = new FileOutputStream("E:\\newstart\\linshi\\stu.bin");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        //2.序列化(写入操作)
        Student zs = new Student("张三", 20);
        oos.writeObject(zs);
        //3.关闭
        oos.close();
        System.out.println("序列化完毕");
    }

4.2 反序列化

代码演示:

   public static void main(String[] args) throws Exception {
        /**
         * 使用ObjectInputStream实现对象的反序列化(读取重构对象)
         */
        //1.创建对象流
        FileInputStream fis = new FileInputStream("E:\\newstart\\linshi\\stu.bin");
        ObjectInputStream ois = new ObjectInputStream(fis);
        //2.读取文件(反序列化)
        Student stu = (Student) ois.readObject();
        //3.关闭
        ois.close();
        System.out.println("反序列化完毕");
        System.out.println(stu.toString());//Student{name='张三', age=20}
    }

4.3 注意事项

  1. 某个类要想序列化必须实现Serializable接口
  2. 序列化类中对象属性要求实现Serializable接口
  3. 序列化版本号ID:serialVersionUID,保证序列化的类和反序列化的类是同一个类
  4. 使用transient(瞬间的)修饰属性,这个属性就不能序列化
  5. 静态属性不能序列化
  6. 序列化多个对象,可以借助集合来实现

注:序列化版本号ID定义:private static final long serialVersionUID = 100L;


5 字符编码

  • IS0-8859-1:收录除ASCII外,还包括西欧、希腊语、泰语、阿拉伯语、希伯来语对应的文字符号。
  • UTF-8:针对Unicode码表的可变长度字符编码
  • GB2312:简体中文
  • GBK:简体中文、扩充
  • BIG5:台湾,繁体中文

注:编码方式和解码方式不一致时,会出现乱码。


6 字符流

代码演示:

	public static void main(String[] args) throws Exception {
        /**
         * 传统字节流读取
         */
        //1.创建FileInputStream对象
        FileInputStream fis = new FileInputStream("E:\\newstart\\linshi\\hello.txt");
        //2.读取
        int data = 0;
        while((data = fis.read()) != -1){//12个字节 4个汉字
            System.out.print((char)data);
        }
        //3.关闭
        fis.close();
    }

6.1 字符流的父类

reader 字符输入流

  • public int read(){}
  • public int read(char[] c){}
  • public int read(char[] b, int off, int len){}

Writer 字符输出流

  • public void write(int n){}
  • public void write(String str){}
  • public void write(char[] c){}

6.2 FileReader

文件字符输入流代码演示:

	public static void main(String[] args) throws Exception {
        /**
         * 使用FileReader读取文件
         */
        //1.创建FileReader 文件字符输入流
        FileReader fr = new FileReader("E:\\newstart\\linshi\\hello.txt");
        //2.读取
        //2.1单个字符读取
//        int data = 0;
//        while ((data = fr.read()) !=-1){//读取一个字符
//            System.out.print((char)data);
//        }
        //2.2字符缓冲区读取
        char[] buf = new char[1024];//2的话一个2个字符
        int count = 0;
        while ((count = fr.read(buf)) != -1){
            System.out.println(new String(buf, 0, count));
        }
        //3.关闭
        fr.close();
    }

6.3 FileWriter

文件字符输出流代码演示:

	public static void main(String[] args) throws Exception {
        /**
         * 使用FileWriter写入文件
         */
        //1.创建FileWriter 文件字符输出流
        FileWriter fw = new FileWriter("E:\\newstart\\linshi\\writer.txt");
        //2.写入
        for (int i = 0; i < 10; i++) {
            fw.write("java是世界上最好的语言\r\n");
            fw.flush();
        }
        //3.关闭
        fw.close();
        System.out.println("执行完毕");
    }

6.4 文本文件复制(案例)

使用FileReaderFileWriter不能复制图片或二进制文件,使用字节流可以复制任意文件

代码演示:

	public static void main(String[] args) throws Exception {
        //1.创建
        FileReader fr = new FileReader("E:\\newstart\\linshi\\writer.txt");
        FileWriter fw = new FileWriter("E:\\newstart\\linshi\\w.txt");
        //2.读写
        int data = 0;
        while ((data = fr.read()) != -1){
            fw.write(data);
            fw.flush();
        }
        //3.关闭
        fr.close();
        fw.close();
        System.out.println("copy完毕");
    }

6.5 字符缓冲流

BufferedReader / BufferedWriter

高效读写、支持输入换行符、可一次写一行读一行

代码演示:

	public static void main(String[] args) throws Exception {
        /**
         * 使用字符缓冲流读取文件
         * BufferdReader
         */
        //1.创建缓冲流
        FileReader fr = new FileReader("E:\\newstart\\linshi\\writer.txt");
        BufferedReader br = new BufferedReader(fr);
        //2.读取
        //2.1 第一种方式
        char[] buf = new char[1024];
        int count = 0;
        while((count = br.read(buf)) != -1){
            System.out.print(new String(buf, 0, count));
        }
        //2.2 第二种方式 一行一行读
        String line = null;
        while((line = br.readLine()) != null){
            System.out.print(line);
        }
        //3.关闭
        br.close();
    }

代码演示:

	public static void main(String[] args) throws Exception {
        /**
         * 使用字符缓冲流写入文件
         * BufferedWriter
         */
        //1.创建缓冲流
        FileWriter fw = new FileWriter("E:\\newstart\\linshi\\buf.txt");
        BufferedWriter bw = new BufferedWriter(fw);
        //2.写入
        for (int i = 0; i < 10; i++) {
            bw.write("好好学习。");
            bw.newLine();//写入一个换行符
            bw.flush();
        }
        //3.关闭
        bw.close();
        System.out.println("执行完毕");
    }

7 打印流

7.1 PrintWriter

封装了print() / println() 方法 支持写入后换行

支持数据原样打印

代码演示:

	public static void main(String[] args) throws Exception {
        /**
         * 演示PrintWriter的使用
         */
        //1.创建一个打印流
        PrintWriter pw = new PrintWriter("E:\\newstart\\linshi\\print.txt");
        //2.打印
        pw.println(97);
        pw.println(true);
        pw.println(3.14);
        pw.println("你好nihao");
        //3.关闭
        pw.close();
        System.out.println("执行完毕");
    }

8 转换流

桥转换流 InputStreamReader / OutputStreamWriter

可将字节流转换为字符流

可设置字符的编码方式,通常使用UTF-8,文件另存为ANSI就是gbk

代码演示:

	public static void main(String[] args) throws Exception {
        /**
         * 使用InputStreamReader读取文件 指定使用的编码
         */
        //1.创建InputStreamReader对象
        FileInputStream fis = new FileInputStream("E:\\newstart\\linshi\\writer.txt");
        InputStreamReader isr = new InputStreamReader(fis, "utf-8");
        //2.读取文件
        int data = 0;
        while ((data = isr.read()) != -1){
            System.out.print((char)data);
        }
        //3.关闭
        isr.close();
    }

代码演示:

	public static void main(String[] args) throws Exception {
        /**
         * 使用OutputStreamWriter 写入文件 指定使用的编码
         */
        //1.创建OutputStreamWriter对象
        FileOutputStream fos = new FileOutputStream("E:\\newstart\\linshi\\writer.txt");
        OutputStreamWriter osw = new OutputStreamWriter(fos, "utf-8");
        //2.写入文件
        for (int i = 0; i < 10; i++) {
            osw.write("我爱北京\r\n");
            osw.flush();
        }
        //3.关闭
        fos.close();
        System.out.println("执行完毕");
    }	

9 File类

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

9.1 四个常量

1.public static final char separatorChar;
	与系统有关的默认名称分隔符。
	此字段被初始化为包含系统属性file.separator 值的第一个字符。在 UNIX 系统上,此字段的值为 '/';在 Microsoft Windows 系统上,它为 '\\'。
2.public static final String separator;
	与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串。
	此字符串只包含一个字符,即 separatorChar。
3.public static final char pathSeparatorChar;
	与系统有关的路径分隔符。
	此字段被初始为包含系统属性 path.separator 值的第一个字符。此字符用于分隔以路径列表 形式给定的文件序列中的文件名。在 UNIX 系统上,此字段为 ':';在 Microsoft Windows 系统上,它为 ';'。                  
4.public static final String pathSeparator;
	与系统有关的路径分隔符,为了方便,它被表示为一个字符串。
	此字符串只包含一个字符,即 pathSeparatorChar。

9.2 常用方法

  • 获取文件或目录的详细信息
String getName():   返回由此抽象路径名表示的文件或目录的名称。
long length() :    返回由此抽象路径名表示的文件的长度。(只能返回文件大小,不能直接返回目录大小)
boolean exists() :  判断此抽象路径名表示的文件或目录是否存在。
boolean isHidden() : 判断此抽象路径名指定的文件是否是一个隐藏文件。
boolean canRead() :  判断应用程序是否可以读取此抽象路径名表示的文件。
boolean canWrite() : 判断应用程序是否可以修改此抽象路径名表示的文件 
long lastModified() : 返回此抽象路径名表示的文件最后一次被修改的时间。(毫秒值)
String toString() :  返回此抽象路径名的路径名字符串。boolean isAbsolute(): 测试File对象对应的文件或目录是否是绝对路径。
String getParent() : 返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回 null。(返回父目录名称) 
File getParentFile() :返回此抽象路径名父目录的抽象路径名;如果此路径名没有指定父目录,则返回 null。(返回父目录的File对象)
  • 获取文件或目录的路径
String getPath() : 将此抽象路径名转换为一个路径名字符串。
File getAbsoluteFile() : 返回此抽象路径名的绝对路径名形式。
String getAbsolutePath():返回此抽象路径名的绝对路径名字符串。 返回绝对路径,从根目录开始导航
File getCanonicalFile(): 返回此抽象路径名的规范形式。
String getCanonicalPath() :返回此抽象路径名的规范路径名字符串。规范路径就是路径里没有./或../或/,会把这些自动解析
  • 操作文件或目录
boolean createNewFile():当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件。(只创建文件)
boolean delete(): 删除此抽象路径名表示的文件或目录。(可以删除文件或删除空目录)删除成功,返回true,失败false。 
boolean equals(Object obj):判断此抽象路径名与给定对象是否相等。
boolean mkdir() : 创建此抽象路径名指定的目录。(只能创建一级目录)必须确保父目录存在,否则创建失败。
boolean mkdirs(): 创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。 (可以创建多级目录)如果父目录不存在,会一同创建父目录
boolean renameTo(File dest) :重新命名此抽象路径名表示的文件。(可以给文件或目录重命名)
  • 判断是文件还是目录
boolean isFile() :判断此抽象路径名表示的文件是否是一个标准文件。
boolean isDirectory():判断此抽象路径名表示的文件是否是一个目录。
  • 获取目录的下一级
String[] list() :返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。
File[] listFiles() :返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。(获取下一级的文件/目录的File对象)
static` `File[] listRoots():列出可用的文件系统根。

9.3 案例(基本以及FileFilter过滤器)

代码演示:

	public static void main(String[] args) throws Exception {
        /**
         *  File类的使用
         *  (1)分隔符
         *  (2)文件操作
         *  (3)文件夹操作
         */
//        separator();
//        fileOpe();
        directoryOpe();
    }
    //(1)分隔符
    public static void separator(){
        System.out.println("路径分隔符" + File.pathSeparator);//;
        System.out.println("名称分隔符" + File.separator);//\
    }

    //(2)文件操作
    public static void fileOpe() throws Exception {
        //1.创建文件
        File file = new File("E:\\newstart\\linshi\\file\\file.txt");
//        System.out.println(file.toString());//E:\newstart\linshi\file\file.txt
        if(!file.exists()){//判断是否存在
            boolean b = file.createNewFile();
            System.out.println("创建结果:" + b);
        }

        //2.删除文件
        //2.1直接删除
//        boolean delres = file.delete();
//        System.out.println("删除结果:"+delres);
        //2.2使用jvm退出时删除
//        file.deleteOnExit();
//        Thread.sleep(5000);//休眠5秒,方便看效果

        //3.获取文件信息
        System.out.println("获取文件的绝对路径:" + file.getAbsolutePath());
        System.out.println("获取路径:" + file.getPath());
        System.out.println("获取文件名称:" + file.getName());
        System.out.println("获取父目录:" + file.getParentFile());
        System.out.println("获取文件长度:" + file.length());//汉字占3个
        System.out.println("文件创建时间:" + new Date(file.lastModified()).toLocaleString());//lastModified()默认是long类型

        //4.判断
        System.out.println("是否可写:" + file.canWrite());
        System.out.println("是否是文件:" + file.isFile());
        System.out.println("是否是隐藏:" + file.isHidden());
    }

    //(3)文件夹操作
    public static void directoryOpe() throws Exception {
        //1.创建文件夹
        File dir = new File("E:\\newstart\\linshi\\file1");
        System.out.println(dir.toString());
        if(!dir.exists()){
            dir.mkdirs();//mkdir()只能创建单级目录
        }

        //2.删除文件夹
        //2.1直接删除
//        boolean delres = dir.delete();//只能删除空目录
//        System.out.println("删除结果:"+delres);
        //2.2使用jvm退出时删除
//        dir.deleteOnExit();
//        Thread.sleep(5000);//休眠5秒,方便看效果

        //3.获取文件信息
        System.out.println("获取文件夹的绝对路径:" + dir.getAbsolutePath());
        System.out.println("获取文件夹路径:" + dir.getPath());
        System.out.println("获取文件夹名称:" + dir.getName());
        System.out.println("获取父目录:" + dir.getParentFile());
        System.out.println("文件夹创建时间:" + new Date(dir.lastModified()).toLocaleString());//lastModified()默认是long类型

        //4.判断
        System.out.println("是否是文件夹:" + dir.isDirectory());
        System.out.println("是否是隐藏:" + dir.isHidden());

        //5.遍历文件夹
        File dir2 = new File("E:\\newstart\\linshi");
        String[] files = dir2.list();//listFiles()返回File类型,list返回String类型
        for (String file : files) {
            System.out.println(file);
        }

        //FileFilter接口的使用(文件过滤器)
        System.out.println("--------FileFilter接口的使用--------");
        File[] files2 = dir2.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                if (pathname.getName().endsWith(".png")) {
                    return true;
                }
                return false;
            }
        });
        for (File file : files2) {
            System.out.println(file.getName());
        }
    }

9.4 递归遍历

代码演示:

	//案例1 递归遍历文件夹
    public static void listDir(File dir) throws Exception {
        File[] files = dir.listFiles();
        System.out.println(dir.getAbsoluteFile());
        if(files != null && files.length > 0) {
            for (File file : files) {
                if(file.isDirectory()) {
                    listDir(file);
                }else{
                    System.out.println(file.getAbsolutePath());
                }
            }
        }
    }

9.5 递归删除

代码演示:

	//案例2 递归删除文件夹
    public static void delDir(File dir) throws Exception {
        File[] files = dir.listFiles();
        if(files != null && files.length > 0) {
            for (File file : files) {
                if(file.isDirectory()) {
                    delDir(file);
                }else{
                    System.out.println(file.getAbsolutePath()+"删除:"+file.delete());
                }
            }
        }
        System.out.println(dir.getAbsolutePath()+"删除:"+dir.delete());//删除文件夹
    }

10 Properties

集合中提到过

Properties:属性集合,继承hashtable,线程安全

特点:

  • 存储属性名和属性值
  • 属性名和属性值都是字符串类型
  • 没有泛型
  • 和流有关

代码演示:

	public static void main(String[] args) throws Exception {
        /**
         * 演示Properties集合的使用
         */
        //1.创建集合
        Properties properties = new Properties();
        //2.添加元素
        properties.setProperty("name", "张三");
        properties.setProperty("age", "20");
        System.out.println(properties.toString());
        //3.删除 remove() clear()
        //4.遍历
        //4.1 keySet
        //4.2 entrySet
        //4.3 stringPropertyNames()
        Set<String> strings = properties.stringPropertyNames();
        for (String string : strings) {
            System.out.println(string+":"+properties.getProperty(string));
        }
        //5.和流有关的方法
        //5.1 list()
//        PrintWriter pw = new PrintWriter("E:\\newstart\\linshi\\print.txt");
//        properties.list(pw);
//        pw.close();

        //5.2 store() 保存
        //可以使用FileOutputStream和FileInputStream(中文乱码会乱码),也可以使用FileWriter和FileReader(中文不乱码)
//        FileWriter fw = new FileWriter("E:\\newstart\\linshi\\print.propertes");
//        properties.store(fw,"注释");
//        fw.close();

        //5.3 load() 加载
        Properties properties2 = new Properties();
        FileReader fr = new FileReader("E:\\newstart\\linshi\\print.propertes");
        properties2.load(fr);
        fr.close();
        System.out.println(properties2.toString());
    }

总结

流的概念:

  • 内存与存储设备之间传输数据的通道。

流的分类:

  • 输入流、输出流;字节流、字符流;节点流、过滤流;

序列化、反序列化:

  • 将对象通过流写入到文件,或将对象通过流读取到内存,必须实现Serializable接口。

File对象:

  • 代表物理盘符中的一个文件或者文件夹。

END

这篇关于Java SE09_I/O框架的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!