Java核心技术卷一 -第十章:IO流

系列文章目录

Java核心技术卷一 -第一章:java“白皮书”的关键术语
Java核心技术卷一 -第三章:数据类型
Java核心技术卷一 -第三章:变量与常量
Java核心技术卷一 -第三章:运算符
Java核心技术卷一 -第三章:字符串
Java核心技术卷一 -第三章:输入与输出
Java核心技术卷一 -第三章:数组
Java核心技术卷一 -第四章:类之间的关系-依赖
Java核心技术卷一 -第四章:预定义类-LocalDate类小应用
Java核心技术卷一 -第四章:构造器
Java核心技术卷一 -第四章:null引用
Java核心技术卷一 -第四章:方法参数
Java核心技术卷一 -第四章:对象构造
Java核心技术卷一 -第五章:覆盖方法与super
Java核心技术卷一 -第五章:super关键字
Java核心技术卷一 -第五章:类的强制类型转换与instanceof操作符
Java核心技术卷一 -第五章:抽象类与abstract关键字
Java核心技术卷一 -第五章:Object类的toString方法
Java核心技术卷一 -第五章:数组列表初识
Java核心技术卷一 -第五章:装箱和拆箱
Java核心技术卷一 -第五章:枚举类再认识
Java核心技术卷一 -第七章:异常
Java核心技术卷一 -第九章:集合
Java核心技术卷一 -第六章:抽象类和接口

文章目录


前言

本人为java初学者,文章内容仅为个人学习总结分享,其中包含了大量Java核心技术卷一里面的文章内容以及一些网站文章内容,由于参考文章过多,在此并不一一列出,如有侵权,请联系删除。

一、IO流概述

1.1、IO流,什么是IO?

I :Input
O :Output

通过可以完成硬盘文件的读和写。

图示:

在这里插入图片描述

1.2、IO流的分类?

有多种分类方式:

一种方式是按照流的方向进行分类:

以内存作为参照物:
往内存中去,叫做输入(Input)。或者叫做读(Read)。
从内存中出来,叫做输出(Output)。或者叫做写(Write)。

另一种方式是按照读取数据方式不同进行分类:

有的流是按照字节的方式读取数据,一次读取1个字节byte,等同于一次读取8个二进制位。
这种流是万能的,什么类型的文件都可以读取。包括:文本文件,图片,声音文件,视频文件,,,,,,
假设文件file.txt,采用字节流的话是这样读的:
a中国bc张三fe
第一次读:一个字节,正好读到‘a’。
第二次读:一个字节,正好读到‘中’字符的一半。
第三次读:一个字节,正好读到‘中’字符的另外一半。

有的流是按照字符的方式读取数据的,一次读取一个字符,这种流是为了方便读取普通文本文件而存在的。
这种流不能读取:图片、声音、视频等文件。只能读取纯文本文件,连word文件都无法读取。
假设文件file.txt,采用字节流的话是这样读的:
a中国bc张三fe
第一次读:‘a’字符(‘a’字符在windows系统中占用1个字节。)
第二次读:‘中’字符(‘中’字符在windows系统中古用2个字节。)

综上所述:流的分类

按照流的方向进行分类:输入流、输出流
按照读取数据方式不同进行分类:字节流、字符流

1.3、java IO流这块有四大家族:

四大家族的首领:

java.io.Inputstream 字节输入流
java.io.Outputstream 字节输出流

java.io.Reader 字符输入流
java.io.Writer 字符输出流

四大家族的首领都是抽象类。(abstract class)

所有的流都实现了:

java.io.Closeable接口,都是可关闭的,都有close()方法。流毕竟是一个管道,这个是内存和硬盘之间的通道,用完之后一定要关闭,
不然会耗费(占用)很多资源。养成好习惯,用完流一定要关闭。

所有的输出流都实现了:

java.io.Flushable接口,都是可刷新的,都有flush()方法。养成一个好惯,输出流在最终输出之后,一定要记得flush()刷新一下。这个刷新表示将通道/管道当中剩余未输出的数据强行输出完(清空管道!)刷新的作用就是清空管道。

注意:如果没有flush()可能会导致丢失数据。

注意:在java中只要"类名"以stream结尾的都是字节流。以"Reader/Writer"结尾的都是字符流。

1.4、需要掌握的流

图示:

在这里插入图片描述

1.5、例子展示

代码展示(FileInputStream):

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Test02 {
    public static void main(String[] args) {
        InputStream is = null;
        try {
            is = new FileInputStream("E:\\讲义\\tmpe.txt");
            byte[] bytes=new byte[4];
/*          第一种简单方法:
            while (true){
                int readCount=is.read(bytes);
                if (readCount==-1){
                    break;
                }
                System.out.print(new String(bytes,0,readCount));
            }*/
            //第二种便捷方法:
            int readCount=0;
            while ((readCount=is.read(bytes))!=-1){
                System.out.print(new String(bytes,0,readCount));
            }
        }catch(FileNotFoundException e) {
            e.printStackTrace();
        }catch(IOException e) {
            e.printStackTrace();
        }finally {
            //在finally语句块当中确保流一定关闭
            try {
                if (is != null){
                    is.close();
                }
            }catch(IOException e) {}
        }
    }
}

结果:
在这里插入图片描述

在这里插入图片描述

代码展示(FiteOutputStream):

提示方法:
在这里插入图片描述

import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Test02 {
    public static void main(String[] args) {
        OutputStream os = null;
        try {
            //ympe.txt文件不存在的时候会自动新建!
            //这种方式谨慎使用,这种方式会先将原文件清空,然后重新写入。
            //fos = new FiteOutputStream("myfile");
            //fos = new FileOutputStream("chopter23/src/tempfile3");
            //以追加的方式在文件末尾写入。不会清空原文件内容
            os = new FileOutputStream("E:\\讲义\\ympe.txt",true);
            byte[] bytes={97,98,99,10};
            //将byte数组全部写出
            os.write(bytes);//abed
            //将byte数组的一部分写出!
            os.write(bytes,0,2);//写出ab
            //写完之后,最后一定要刷新
            os.flush();
        }catch(FileNotFoundException e) {
            e.printStackTrace();
        }catch(IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if (os != null) {
                    os.close();
                }
            }catch(IOException e) {}
        }
    }
}

结果:
在这里插入图片描述

代码展示(文件复制):

import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Test02 {
    public static void main(String[] args) {
        InputStream is = null;
        OutputStream os = null;
        try {
            is = new FileInputStream("E:\\讲义\\tmpe.txt");
            os = new FileOutputStream("E:\\讲义\\xmti.txt");

            //一边读,一边写
            byte[]bytes=new byte[1024*1024];
            int readCount = 0;
            while ((readCount = is.read(bytes)) != -1) {
                os.write(bytes,0,readCount);//将此数组从第0开始,读readCount个字节写入此文件
            }

            //刷新,输出流最后刷新
            os.flush();

            System.out.println("文件复制完毕!");
        }catch(FileNotFoundException e) {
            e.printStackTrace();
        }catch(IOException e) {
            e.printStackTrace();
        }finally {
                if (is != null){
                    try {
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (os != null) {
                    try {
                        os.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
        }
    }
}

结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码展示(BufferedInputStream与BufferedOutputStream文件复制):

import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Test02 {
    public static void main(String[] args) {
        InputStream is = null;
        OutputStream os = null;
        try {
            //当一个流的构造方法中需要一个流的时候,这个被传进来的流叫做:节点流。
            //外部负责包装的这个流,叫做:包装流,还有一个名字叫做:处理流。
            //像当前这个程序来说:FileInputStream就是一个节点流。BufferedInputStream就是包装流/处理流。
            is = new BufferedInputStream(
                    new FileInputStream("E:\\\\讲义\\\\tmpe.txt"));
            os = new BufferedOutputStream(
                    new FileOutputStream("E:\\\\讲义\\\\xmti.txt"));
            int b = 0;
            while ((b = is.read()) != -1) {
                os.write(b);
            }
            //手动调用 flush,将缓冲区中的内容写入到磁盘
            //也可以不用手动调用,缓存区满了自动回清楚了
            //而当输出流关闭的时候也会先调用flush
            os.flush();
            System.out.println("文件复制完毕!");
        }catch(FileNotFoundException e) {
            e.printStackTrace();
        }catch(IOException e) {
            e.printStackTrace();
        }finally {
                if (is != null){
                    try {
                        //在 close 前会先调用 flush
                        //对于包装流来说,只要关闭最外层流就行,里西的节点流会自动关闭。(可以看源代码。)
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (os != null) {
                    try {
                        os.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
        }
    }
}

结果:
在这里插入图片描述

代码展示(InputStreamReader):

在这里插入图片描述

1.6、挑战例子:拷贝目录

图示代码:

主函数:
在这里插入图片描述
copyDir方法:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码展示(InputStreamReader):

import java.io.*;

public class CopyAll {
    public static void main(String[] args) {
        //创建流
        //拷贝源
        File srcFile=new File("D:\\C语言作业\\IdeaProjects\\Project01\\Module01\\src");
        //拷贝目标
        File destFile=new File("D:\\拷贝代码\\a");
        //调用方法拷贝
        copyDir(srcFile,destFile);
    }

    /**
     * 拷贝目录
     * srcFile 拷贝源
     * desstFile 拷贝目标
     */
    private static void copyDir(File srcFile,File destFile){
        if(srcFile.isFile()){
            //srcFile如果是一个文件的话,递归结束。
            //是文件的时候需要拷贝。
            FileInputStream in=null;
            FileOutputStream out=null;
            try {
                //读这个文件
                in=new FileInputStream(srcFile);
                //写到这个文件
                String path=(destFile.getAbsolutePath().endsWith("\\")?destFile.getAbsolutePath():destFile.getAbsolutePath()+"\\")+srcFile.getAbsolutePath().substring(3);
                out=new FileOutputStream(path);
                //一边读一边写,[1024*1024]表示最多一次读入1MB
                byte[] bytes=new byte[1024*1024];//1MB
                int readCount=0;
                while((readCount=in.read(bytes))!=-1){
                    out.write(bytes,0,readCount);
                }
                //刷新
                out.flush();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if(out!=null){
                    try {
                        out.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(in!=null){
                    try {
                        in.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return;
        }
        //获取源下面的子目录
        File[] files=srcFile.listFiles();
        for(File file:files){
            //获取所有文件的(包括目录和文件)绝对路径
            //System.out.println(file.getAbsoluteFile());
            if(file.isDirectory()){
                //新建对应的目录
                String srcDir=file.getAbsolutePath();
                String destDir=(destFile.getAbsolutePath().endsWith("\\")?destFile.getAbsolutePath():destFile.getAbsolutePath()+"\\")+srcDir.substring(3);
                File newFile=new File(destDir);
                if(!newFile.exists()){
                    newFile.mkdirs();
                }
            }
            //递归调用
            copyDir(file,destFile);
        }
    }
}

二、File类

2.1、File类和四大家族没有关系,所以File类不完成文件的读和写

2.2、File对象代表什么?

文件和目录路径名的抽象表示形式。

C:\Drivers 这是一个File对象。
C:\Drivers \Lan \Realtek \Readme.txt 也是File对象。

一个File对象有可能对应的是目录,也可能是文件。
File只是一个路程名的抽象表示形式。

2.3、需要掌量File类中常用的方法

代码展示:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码展示:

在这里插入图片描述

代码展示:

在这里插入图片描述

三、序列化与反序列化

3.1、序列化:

在这里插入图片描述

3.2、参与序列化和反序列化的对象,必须实serializable接口

3.3、注意:通过源代码发现,Serializable接口只是一个标志接口:

public interface Serializable { }

这个接口当中什么代码都没有。

那么它起到一个什么作用呢?

起到标识的作用,标志的作用,java虚拟机看到这个类实现了这个接口,可能会对这个类进行特殊待遇。
Serializable这个标志接口是给java虚拟机参考的,java虚拟机看到这个接口之后,会为该类自动生成一个序列化版本号。

3.4、transient关键字表示游离的,不参与序列化。

private transient String name;//name不参与序列化操作!

3.5、Java虚拟机看到Serializable接口之后,会自动生成一个序列化版本号

java虚拟机会默认提供这个序列化版本号。
建议将序列化版本号手动的写出来,不建议自动生成。这样即便以后代码修改了,java虚拟机也能识别这个类,而不是将其识别为其它异类。

private static final long serialVersionUID =45645654345654345;

代码写在main方法中。

四、IO与Properties的联合应用

4.1、IO+Properties的联合应用非常好的一个设计理念:

以后经常改变的数据,可以单独写到一个文件中,使用程序动态读取。将来只要修改这个文件(也称为配置文件)的内容,jav代码不需要改动,不需要重新编译,服务器也不需要重启。可以拿到动态的信息。

提醒:

Properties是一个Map集合,key value都是String.类型。可以将配置文件中的数据加载到Properties对象当中。

图示代码:

在这里插入图片描述
测试文本:
在这里插入图片描述
结果:
在这里插入图片描述

代码展示:

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;

public class PropertiesTest01 {
    public static void main(String[] args) throws IOException {
        //新建一个输入流对象
        FileReader reader=new FileReader("D:\\C语言作业\\IdeaProjects\\Project01\\xu.txt");

        //新建一个map集合
        Properties pro=new Properties();

        //将文件中的数据加载到map集合中
        pro.load(reader);

        //通过key来获取value
        String username=pro.getProperty("key1");
        System.out.println(username);

        //关闭
        reader.close();
    }
}

总结

以上就是本文的内容,记录了一些关于java“IO流”的内容,本人也是刚开始接触java,不能保证总结内容的正确性,若是有错误的话,欢迎大家指出,谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luodiab

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值