Java文件IO流知识点总结

本文详细介绍了Java中的File类,包括构造方法、文件操作以及路径处理。接着讲解了递归的概念和应用场景。接着深入探讨了IO流的分类,如字节流、字节缓冲流、字符流、字符缓冲流,以及特殊操作流,如标准输入输出流、打印流、对象序列化和反序列化。最后提到了Properties集合的使用。总结了IO流的重要知识点,强调了在实际编程中如何选择合适的流类型。

目录

File类

递归

IO流

字节流、字节缓冲流

字符流、字符缓冲流

特殊操作流

Properties集合

总结

File类


概述:

  • 它是文件和目录路径名的抽象表示

  • 文件和目录是可以通过File封装成对象的

  • 对于File而言,其封装的并不是一个真正存在的文件,仅仅是一个路径名而已它可以是存在的,也可以是不存在的。将来是要通过具体的操作把这个路径的内容转换为具体存在的

构造方法:

方法名说明
File(String pathname)通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例
File(String parent, String child)从父路径名字符串和子路径名字符串创建新的 File实例
File(File parent, String child)从父抽象路径名和子路径名字符串创建新的 File实例

创建功能:

方法名说明
public boolean createNewFile()当具有该名称的文件不存在时,创建一个由该抽象路径名命名的新空文件
public boolean mkdir()创建由此抽象路径名命名的目录
public boolean mkdirs()创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录

判断、获取和删除功能:

判断功能
public boolean isDirectory()测试此抽象路径名表示的File是否为目录
public boolean isFile()测试此抽象路径名表示的File是否为文件
public boolean exists()测试此抽象路径名表示的File是否存在
获取功能
public String getAbsolutePath()返回此抽象路径名的绝对路径名字符串
public String getPath()将此抽象路径名转换为路径名字符串
public String getName()返回由此抽象路径名表示的文件或目录的名称
public String[] list()返回此抽象路径名表示的目录中的文件和目录的名称字符串数组
public File[] listFiles()返回此抽象路径名表示的目录中的文件和目录的File对象数组
删除功能
public boolean delete()删除由此抽象路径名表示的文件或目录

绝对路径和相对路径:

  • 绝对路径:完整的路径名不需要任何其他信息就可以定位它所表示的文件。例如:E:\itcast\java.txt

  • 相对路径:必须使用取自其他路径名的信息进行解释。例如:myFile\java.txt

递归


概述:

  • 以编程的角度来看,递归指的是方法定义中调用方法本身的现象

  • 把一个复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解

  • 递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算

递归案例:

public class DiGuiDemo {
    public static void main(String[] args) {
        //回顾不死神兔问题,求第20个月兔子的对数
        //每个月的兔子对数:1,1,2,3,5,8,...
        System.out.println(f(20));
    }
     /*
        递归解决问题,首先就是要定义一个方法:
            定义一个方法f(n):表示第n个月的兔子对数
            那么,第n-1个月的兔子对数该如何表示呢?f(n-1)
            同理,第n-2个月的兔子对数该如何表示呢?f(n-2)

        StackOverflowError:当堆栈溢出发生时抛出一个应用程序递归太深
     */
    public static int f(int n) {
        if(n==1 || n==2) {
            return 1;
        } else {
            return f(n - 1) + f(n - 2);
        }
    }
}

注意事项:

  • 递归一定要有出口否则内存溢出

  • 递归虽然有出口,但是递归的次数也不宜过多否则内存溢出

IO流


概述:

  • IO:输入/输出(Input/Output)

  • 流:是一种抽象概念,是对数据传输的总称。也就是说数据在设备间的传输称为流,流的本质是数据传输

  • IO流就是用来处理设备间数据传输问题的。常见的应用:文件复制;文件上传;文件下载

分类:

  • 字节流、字节缓冲流

    • 字节输入流;字节输出流;字节缓冲输入流;字节缓冲输出流

  • 字符流、字符缓冲流

    • 字符输入流;字符输出流;字符缓冲输入流;字符缓冲输出流

  • 特殊操作流

    • 标准输入输出流打印流对象序列化流对象反序列化流

使用场景:

  • 如果操作的是纯文本文件,优先使用字符流

  • 如果操作的是图片、视频、音频等二进制文件。优先使用字节流

  • 如果不确定文件类型,优先使用字节流。字节流是万能的流

字节流、字节缓冲流


抽象基类:

  • InputStream:这个抽象类是表示字节输入流的所有类的超类

  • OutputStream:这个抽象类是表示字节输出流的所有类的超类

  • 子类名特点:子类名称都是以其父类名作为子类名的后缀

字节输出流:FileOutputStream(String name)创建文件输出流以指定的名称写入文件

字节输出流写数据的步骤:

  • 创建字节输出流对象 (调用系统功能创建了文件,创建字节输出流对象,让字节输出流对象指向文件)

  • 调用字节输出流对象的写数据方法

  • 释放资源 (关闭此文件输出流并释放与此流相关联的任何系统资源)

写数据的三种方式:

方法名说明
void write(int b)将指定的字节写入此文件输出流 一次写一个字节数据
void write(byte[] b)将 b.length字节从指定的字节数组写入此文件输出流 一次写一个字节数组数据
void write(byte[] b, int off, int len)将 len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流 一次写一个字节数组的部分数据

写数据实现换行:不同系统下实现的换行代码不同

  • windows:\r\n

  • linux:\n

  • mac:\r

追加写入数据:

  • public FileOutputStream(String name,boolean append)

  • 创建文件输出流以指定的名称写入文件。如果第二个参数为true ,则字节将写入文件的末尾而不是开头

写数据加异常处理:

try{
    可能出现异常的代码;
}catch(异常类名 变量名){
    异常的处理代码;
}finally{
    执行所有清除操作;
}

finally特点:被finally控制的语句一定会执行,除非JVM退出

异常处理案例:

public class FileOutputStreamDemo {
    public static void main(String[] args) {
        //加入finally来实现释放资源
        FileOutputStream fos = null;
        //异常处理
        try {
            //设置文件路径(相对路径)
            fos = new FileOutputStream("myByteStream\\fos.txt");
            //写入数据到文件
            fos.write("hello".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //判断fos是否为null
            if(fos != null) {
                //异常处理
                try {
                    //释放资源
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

读数据:一次读一个字节数据、一次读一个字节数组数据

字节输入流:FileInputStream(String name)通过打开与实际文件的连接来创建一个FileInputStream,该文件由文件系统中的路径名name命名

字节输入流读取数据的步骤:

  • 创建字节输入流对象

  • 调用字节输入流对象的读数据方法

  • 释放资源

一次读一个字节数组的方法:

  • public int read(byte[] b):从输入流读取最多b.length个字节的数据

  • 返回的是读入缓冲区的总字节数,也就是实际的读取字节个数

字节流读数据案例:

public class FileInputStreamDemo {
    public static void main(String[] args) throws IOException {
        //创建字节输入流对象
        //myByteStream\\fos.txt表示要读取的文件(相对路径)
        FileInputStream fis = new FileInputStream("myByteStream\\fos.txt");

        //一次读一个字节数据
        int by;
        while ((by=fis.read())!=-1) {
            System.out.print((char)by);
        }

        //一次读一个字节数组数据
        byte[] bys = new byte[1024]; //1024及其整数倍
        int len;
        while ((len=fis.read(bys))!=-1) {
            System.out.print(new String(bys,0,len));
        }
        //释放资源
        fis.close();
    }
}

字节流图解:

字节缓冲流:

  • BufferOutputStream:该类实现缓冲输出流。 通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用

  • BufferedInputStream:创建BufferedInputStream将创建一个内部缓冲区数组。 当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,一次很多字节

 构造方法:

方法名说明
BufferedOutputStream(OutputStream out)创建字节缓冲输出流对象
BufferedInputStream(InputStream in)创建字节缓冲输入流对象

字节缓冲流读写数据案例:

public class BufferStreamDemo {
    public static void main(String[] args) throws IOException {
        //字节缓冲输出流:BufferedOutputStream(OutputStream out)
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("myByteStream\\bos.txt"));
        //写数据
        bos.write("hello\r\n".getBytes());
        bos.write("world\r\n".getBytes());
        //释放资源
        bos.close();
    
        //字节缓冲输入流:BufferedInputStream(InputStream in)
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("myByteStream\\bos.txt"));

        //一次读取一个字节数据
        int by;
        while ((by=bis.read())!=-1) {
            System.out.print((char)by);
        }

        //一次读取一个字节数组数据
        byte[] bys = new byte[1024];
        int len;
        while ((len=bis.read(bys))!=-1) {
            System.out.print(new String(bys,0,len));
        }
        //释放资源
        bis.close();
    }
}

字符流、字符缓冲流


抽象基类:

  • Reader:字符输入流的抽象类

  • Writer:字符输出流的抽象类

字符流中的编码解码:

  • InputStreamReader:是从字节流到字符流的桥梁。它读取字节,并使用指定的编码将其解码为字符,它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集

  • OutputStreamWriter:是从字符流到字节流的桥梁。使用指定的编码将写入的字符编码为字节,它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集

构造方法:

方法名说明
InputStreamReader(InputStream in)使用默认字符编码创建InputStreamReader对象
InputStreamReader(InputStream in,String chatset)使用指定的字符编码创建InputStreamReader对象
OutputStreamWriter(OutputStream out)使用默认字符编码创建OutputStreamWriter对象
OutputStreamWriter(OutputStream out,String charset)使用指定的字符编码创建OutputStreamWriter对象

写数据的五种方式、刷新和关闭

方法名说明
void write(int c)写一个字符
void write(char[] cbuf)写入一个字符数组
void write(char[] cbuf, int off, int len)写入字符数组的一部分
void write(String str)写一个字符串
void write(String str, int off, int len)写一个字符串的一部分
刷新和关闭
flush()刷新流,之后还可以继续写数据
close()关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据

读数据的两种方式:

方法名说明
int read()一次读一个字符数据
int read(char[] cbuf)一次读一个字符数组数据

PS:字符流写数据可直接根据方法实现,字符流读数据和字节流读数据的代码大同小异 (基本一样),可参考上述代码自行实现。

字符流图解:

字符缓冲流:

  • BufferedWriter:文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入,可以指定缓冲区大小,或者可以接受默认大小。默认值足够大,可用于大多数用途

  • BufferedReader:从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取,可以指定缓冲区大小,或者可以使用默认大小。 默认值足够大,可用于大多数用途

构造方法:

方法名说明
BufferedWriter(Writer out)创建字符缓冲输出流对象
BufferedReader(Reader in)创建字符缓冲输入流对象

特有功能:

方法名说明
void newLine()写一行行分隔符,行分隔符字符串由系统属性定义
String readLine()读一行文字。 结果包含行的内容的字符串,不包括任何行终止字符如果流的结尾已经到达,则为null

字符缓冲流读写数据案例:使用特有功能

public class BufferedStreamDemo {
    public static void main(String[] args) throws IOException {
        //创建字符缓冲输出流
        BufferedWriter bw = new BufferedWriter(new FileWriter("myCharStream\\bw.txt"));

        //写数据
        for (int i = 0; i < 10; i++) {
            bw.write("hello" + i);
            bw.newLine(); //换行
            bw.flush(); //刷新
        }
        //释放资源
        bw.close();

        //创建字符缓冲输入流
        BufferedReader br = new BufferedReader(new FileReader("myCharStream\\bw.txt"));
        
        //读数据
        String line;
        while ((line=br.readLine())!=null) {
            System.out.println(line);
        }
        //释放资源
        br.close();
    }
}

特殊操作流


标准输入输出流:

  • System类中有两个静态的成员变量

    • public static final InputStream in:标准输入流通常该流对应于键盘输入或由主机环境或用户指定的另一个输入源

    • public static final PrintStream out:标准输出流通常该流对应于显示输出或由主机环境或用户指定的另一个输出目标

  • 输出语句的本质:是一个标准的输出流

    • PrintStream ps = System.out;

    • PrintStream类有的方法,System.out都可以使用

打印流特点:

  • 只负责输出数据,不负责读取数据

  • 永远不会抛出IOException

  • 有自己的特有方法

分类:字节打印流 (PrintStream);字符打印流 (PrintWriter)

字节打印流:

  • PrintStream(String fileName):使用指定的文件名创建新的打印流

  • 使用继承父类的方法写数据,查看的时候会转码;使用自己的特有方法写数据,查看的数据原样输出

  • 可以改变输出语句的目的地,public static void setOut(PrintStream out):重新分配“标准”输出流

字符打印流构造方法:

方法名说明
PrintWriter(String fileName)使用指定的文件名创建一个新的PrintWriter,而不需要自动执行刷新
PrintWriter(Writer out, boolean autoFlush)创建一个新的PrintWriter out:字符输出流 autoFlush: 一个布尔值,如果为真,则println , printf ,或format方法将刷新输出缓冲区

对象序列化概述:

  • 对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象

  • 这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息

  • 字节序列写到文件之后,相当于文件中持久保存了一个对象的信息

  • 反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化

对象序列化流 (ObjectOutputStream)将Java对象的原始数据类型和图形写入OutputStream。 可以使用ObjectInputStream读取(重构)对象。 可以通过使用流的文件来实现对象的持久存储。 如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象

构造方法:ObjectOutputStream(OutputStream out):创建一个写入指定的OutputStream的ObjectOutputStream

序列化对象的方法:void writeObject(Object obj):将指定的对象写入ObjectOutputStream

注意事项:

  • 一个对象要想被序列化,该对象所属的类必须实现Serializable接口

  • Serializable是一个标记接口,实现该接口,不需要重写任何方法

对象反序列化流 (ObjectInputStream)ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象

构造方法:ObjectInputStream(InputStream in):创建从指定的InputStream读取的ObjectInputStream

反序列化对象的方法:Object readObject():从ObjectInputStream读取一个对象

关于序列化ID (serialVersionUID)出现的问题及解决方式:

用对象序列化流序列化了一个对象后,假如我们修改了对象所属的类文件,读取数据会抛出InvalidClassException异常,如何解决?
- 重新序列化
- 给对象所属的类加一个serialVersionUID 
- private static final long serialVersionUID = 42L;

一个对象中的某个成员变量的值不想被序列化,该如何实现?
- 给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程

Properties集合


概述:

  • 是一个Map体系的集合类

  • Properties可以保存到流中或从流中加载

  • 属性列表中的每个键及其对应的值都是一个字符串

特有方法:

方法名说明
Object setProperty(String key, String value)设置集合的键和值,都是String类型,底层调用 Hashtable方法 put
String getProperty(String key)使用此属性列表中指定的键搜索属性
Set<String> stringPropertyNames()从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串

Properties和IO流相结合的方法:

方法名说明
void load(InputStream inStream)从输入字节流读取属性列表(键和元素对)
void load(Reader reader)从输入字符流读取属性列表(键和元素对)
void store(OutputStream out, String comments)将此属性列表(键和元素对)写入此 Properties表中,以适合于使用 load(InputStream)方法的格式写入输出字节流
void store(Writer writer, String comments)将此属性列表(键和元素对)写入此 Properties表中,以适合使用 load(Reader)方法的格式写入输出字符流

总结

        本期关于Java中文件IO流知识点的总结就到这里了,可以发现该部分的知识点又多又杂,出现了大量的构造方法以及部分特有的方法,很容易造成知识点的记忆混乱,但是只要善于总结观察,多运用多思考,就会发现其中的知识并不复杂也很好掌握。为了能够把本期的知识点掌握的更加牢固,下期小编用本期学到的知识点给大家介绍一个有趣的小游戏程序,期待你的关注~

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

South.return

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

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

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

打赏作者

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

抵扣说明:

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

余额充值