IO流概述

什么是IO流?

​ I:Input

​ O:Output

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

IO流的分类?

有多种分类方式:

​ 一种是按照流的方向分类:

​ 往内存中去,叫做输入(Input)。或者叫做读(Read)。

​ 从内存里出来,叫做输出(Output)。或者叫做写(Write)。

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

​ 有的流是按照字节的方式读取数据,一次读取1个字节byte,等同于一次读取8个二进制。这种流是万能的,什么类型的文件都可以读取,包括:文本文件,图片,声音文件,视频文件。

​ 有的流是按照字符的方式读取数据的,一次读取一个字符,这种流是为了方便读取普通文本文件而存在的,这种流不能读取:图片,声音,视频等文件。只能读取纯文本文件,连word文件都无法读取。

综上所述:流的分类

​ 输入流,输出流,

​ 字节流,字符流

Java中所有的流都是在:java.io.*;下。

Java IO流四大家族:

java.io.InputStream 字节输入流

java.io.OutoutStream 字节输出流

java.io.Reader 字符输入流

java.io.Wirter 字符输出流

所有的流都实现了:java.io.Closeable接口,都是可关闭的,都有close()方法。

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

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

注意:在Java中只要“类名”以Stream结尾的都是字节流。以“Reader/Wirter"结尾的都是字符流。

java.io包下需要掌握的流有16个:

​ 文件专属:

​ java.io.FileInputStream

​ java.io.FileOutputStream

​ 转换流:(将字节流转换为字符流)

​ java.io.InputStreamReader

​ java.io.OutStreamWriter

​ 缓冲流专属:

​ java.io.BufferedReader

​ java.io.BufferedWriter

​ java.io.BufferedInputStream

​ java.io.BufferedOutputStream

​ 数据流专属:

​ java.io.DataInputStream

​ java.io.DataOutputStream

​ 标准输出流:

​ java.io.PritsWriter

​ java.io.PrintStream

​ 对象专属流:

​ java.io.ObjectInputStream

​ java.io.ObjectOutputStream

1 文件流

FileInputStream

文件字节输入流,万能的,任何类型的文件都可以采用这个流来读。

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FileInputStreamTest01 {
    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("D:\\Study\\Java\\test");
            int readdate = fis.read();//读取字节本身
            System.out.println(readdate);//97 第一个字节
            readdate = fis.read();
            System.out.println(readdate);//98 第二个字节
            readdate = fis.read();
            System.out.println(readdate);//99 第二个字节
            readdate = fis.read();
            System.out.println(readdate);//-1 三个字节已经读完
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {//避免空指针异常
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FileInputStreamTest02 {
    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("D:\\Study\\Java\\test");
            while (true) {
                int readata = fis.read();
                if (readata == -1) {
                    break;
                }
                System.out.println(readata);
            }

            //改造while循环
            int rdata = 0;
            while ((rdata = fis.read()) != -1) {
                System.out.println(rdata);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

一次读取一个字节byte,这样内存和硬盘交互太频繁,基本上时间/资源都耗费在交互上面了。

int read(byte[] b)

​ 一次最多读取b.Lengh个字节。

​ 减少硬盘和内存的交互,提高程序的执行效率。往byte[]数组中读。

import java.io.FileInputStream;
import java.io.IOException;

public class FileImputStreamTest03 {
    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("D:\\Study\\Java\\test");
            //准备一个长度为4的数组
            byte[] bytes = new byte[4];
            //把byte数组转换成字符串,读到多少就转换多少
            int readCount = 0;
            while ((readCount = fis.read(bytes)) != -1) {
                System.out.println(new String(bytes, 0, readCount));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

available();还剩下多少字节没有读

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FileInputStreamtest04 {
    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("D:\\Study\\Java\\test");
            //读取一个字节
            int readdata = fis.read();
            System.out.println("还剩下多少个字节没有读:" + fis.available());

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

skip();跳过几个字节不读取

            fis.skip(2);//跳过几个字节不读
            System.out.println(fis.read());

FileOutpitStream

文件字节输出流,负责写

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileOutputStreamTest01 {
    public static void main(String[] args) {
        FileOutputStream fos = null;
        try {
            //没有文件会新建
            //fos = new FileOutputStream("D:\\Study\\Java\\test");
            //追加
            fos = new FileOutputStream("D:\\Study\\Java\\test", true);
            byte[] bytes = {97, 98, 99, 100};
            //先将原文件清空再写入
            fos.write(bytes);
            fos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

使用FileInputStream+FileOutputStream完成文件的拷贝

拷贝过程一边读,一边写

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class Copy01 {
    public static void main(String[] args) {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream("D:\\Study\\Java\\test");
            fos = new FileOutputStream("D:\\Study\\Java\\copy");
            //准备数组
            byte[] bytes = new byte[1024 * 1024];//1M(一次最多拷贝1M)
            int readCount = 0;
            while ((readCount = fis.read(bytes)) != -1) {
                fos.write(bytes, 0, readCount);
            }
            //刷新,输出流最后要刷新
            fos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

FileReader

文本字符输入流,只能读取普通文本。

读取文本内容,比较方便,快捷。

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

public class FileReaderTest01 {
    public static void main(String[] args) {
        FileReader reader = null;
        try {
            reader = new FileReader("D:\\Study\\Java\\test");
            char[] chars = new char[2];
            int readerCount = 0;
            while ((readerCount = reader.read(chars)) != -1) {
                System.out.print(new String(chars, 0, readerCount));
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

FileWriter

文件字符输出流:写

只能输出普通文本。

import java.io.FileWriter;
import java.io.IOException;

public class FileWriterTest01 {
    public static void main(String[] args) {
        FileWriter out = null;
        try {
            //追加后面加true
            //out = new FileWriter("D:\\Study\\Java\\test",true);
            out = new FileWriter("D:\\Study\\Java\\test");
            //重写会覆盖
            out.write("提莫队长正在待命!");
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

使用FileReader+FilwWriter拷贝文件

一边读一边写

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Copy02 {
    public static void main(String[] args) {
        FileReader reader = null;
        FileWriter writer = null;
        try {
            reader = new FileReader("D:\\Study\\Java\\test");
            writer = new FileWriter("D:\\Study\\Java\\copy");
            char[] chars = new char[1024 * 512];
            int readCount = 0;
            while ((readCount = reader.read(chars)) != -1) {
                writer.write(chars, 0, readCount);
            }
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2 缓冲流

BufferedReader

带有缓冲区的字符输入流

使用这个流的时候不需要自定义char数组,或者说不需要自定义byte数组。自带缓冲。

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderTest01 {
    public static void main(String[] args) throws IOException {
        FileReader reader = new FileReader("D:\\Study\\Java\\test");
        //当一个流的构造方法中需要一个流的时候,被传进来的流叫做:节点流。
        //外部负责包装的这个流,叫做:包装流,还有一个名字叫做:处理流。
        //FileReader 节点流   BufferedReader  包装流/处理流
        BufferedReader br = new BufferedReader(reader);
        //读第一行  不带换行符
        String firstLine = br.readLine();
        System.out.println(firstLine);
        //到达文件末尾会返回一个null
        String s = null;
        while ((s = br.readLine()) != null) {
            System.out.println(s);
        }
        //关闭流
        //对于包装流来说,只需要关闭最外层的流即可,里面的节点流会自动关闭。
        br.close();
    }
}

通过转换流转换(将字节流转换为字符流)

import java.io.*;

/**
 * @author wcs
 * @date 2021/8/12 18:52
 */
public class BufferedReaderTest02 {
    public static void main(String[] args) throws IOException {
        //字节流
        FileInputStream in = new FileInputStream("D:\\Study\\Java\\test");
        //字节流不能给BufferedReade
       // BufferedReader reader = new BufferedReader(in);
        //通过转换流转换(将字节流转换为字符流)
        InputStreamReader reader = new InputStreamReader(in);
        BufferedReader br = new BufferedReader(reader);
        System.out.println(br.readLine());
        String s = null;
        while ((s = br.readLine()) != null){
            System.out.println(s);
        }
        br.close();
    }
}

BufferedWriter

带有字符缓冲的字符流

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedWriterTest01 {
    public static void main(String[] args) throws IOException {
        FileWriter writer = new FileWriter("D:\\Study\\Java\\test", true);
        BufferedWriter br = new BufferedWriter(writer);
        br.write("德玛西亚之力");
        br.append("\n");
        br.write("德玛西亚之力");
        br.append("A");
        br.flush();
        br.close();
    }
}

3 数据流

DataOutputStream

import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class DataOutputStreamTest01 {
    public static void main(String[] args) throws IOException {
        DataOutputStream dos = new DataOutputStream(new FileOutputStream("D:\\Study\\Java"));
        //写数据
        byte b = 100;
        short t = 200;
        char c = 'a';
        long l = 400L;
        float f = 3.14f;
        int i = 300;
        //写
        dos.writeByte(b);
        dos.writeShort(t);
        dos.writeInt(i);
        dos.writeLong(400L);
        //刷新
        dos.flush();
    }
}

DataInputStream

数据字节输入流。

DataOutStream写的文件,只能使用DataInputStream去读。并且读的时候你需要提取知道写入的顺序。

读的顺序和写的顺序一致,才能正常取出数据。

import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;

public class DataInputStreamTest01 {
    public static void main(String[] args) throws IOException {
        DataInputStream dis = new DataInputStream(new FileInputStream("D:\\Study\\Java"));
        byte b = dis.readByte();
        short t = dis.readShort();
        int i = dis.readInt();
        long l = dis.readLong();
        System.out.println(b);
        System.out.println(t);
        System.out.println(i);
        System.out.println(l);
        dis.close();
    }
}

4 标准输出流

PrintStream

标准的字节输出流。默认输出到控制台。

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;

public class PrintStreamTest01 {
    public static void main(String[] args) throws FileNotFoundException {
        System.out.println("hello world");

        PrintStream ps = System.out;
        ps.println("jack");
        ps.println(123);
        //标准输出流不需要关闭

        //改变输出方向
        //标准输出流不再指向控制台,指向test文件
        System.setOut(new PrintStream(new FileOutputStream("D:\\Study\\Java\\test")));
        System.out.println("hello");
        System.out.println("jack");

    }
}
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 日志工具
 *指向一个日志文件
 */
public class Logger {
    public static void main(String[] args) throws FileNotFoundException {
        System.setOut(new PrintStream(new FileOutputStream("D:\\Study\\Java\\log.txt")));
        Date nowtime = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String strTime = sdf.format(nowtime);
        System.out.println(strTime);
    }
}

4 对象流

ObjectOutputStream

参与序列化和反序列化的对象必须实现Serializable接口。

这个接口起到标识作用,Java虚拟机看到这个类实现了这个接口,可能会对这个类进行特殊待遇。

import java.io.*;

public class ObjectOutputStreamTest01 {
    public static void main(String[] args) throws IOException {
        //创建Student对象
        Student s = new Student(111, "jack");
        //序列化
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("students"));
        //序列化对象
        oos.writeObject(s);
        //刷新
        oos.flush();
        //关闭
        oos.close();

    }
}

class Student implements Serializable {
    int no;
    String name;

    public Student() {

    }

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

ObjectInputStream

反序列化

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;

public class ObjectInputStreamTest01 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("students"));
        ;
        //开始反序列化
        Object obj = ois.readObject();
        //反序列化回来是一个学生对象,所以会调用学生对象的toString方法
        System.out.println(obj);
        ois.close();
    }
}

也可以把对象放到集合当中,序列集合,可以达到一个序列化多个对象。

5 File类

文件和目录表示的抽象形式

File类中常用方法:

import java.io.File;
import java.io.IOException;

public class FileTest01 {
    public static void main(String[] args) throws IOException {
        //创建file对象
        File f1 = new File("D:\\user");
        //判断是否存在
        System.out.println(f1.exists());
        //如果不存在  新建
//        if (!f1.exists()){
//            //以文件的形式新建
//            f1.createNewFile();
//        }
        //如果不存在以目录的形式新建
//        if (!f1.exists()){
//            f1.mkdir();
//        }
        //创建多层目录
//        File f2 = new File("D:\\user\\a\\c");
//        if (!f2.exists()){
//            f2.mkdirs();
//        }
        File f3 = new File("D:\\Study\\Java\\log.txt");
        //获取文件父路径
        String path = f3.getParent();
        System.out.println(path);
        File pf = f3.getParentFile();
        System.out.println(pf);
        //获取绝对路径
        System.out.println(f3.getAbsolutePath());
    }
}
import java.io.File;

public class FileTest02 {
    public static void main(String[] args) {
        File f1 = new File("D:\\Study\\Java\\log.txt");
        //获取文件名
        System.out.println(f1.getName());
        //判断是否是一个目录
        System.out.println(f1.isDirectory());//false
        //判断是否是一个文件
        System.out.println(f1.isFile());//trye
        //获取文件最后一次修改时间
        System.out.println(f1.lastModified());//long类型毫秒数
        //获取文件大小
        System.out.println(f1.length());
    }
}
import java.io.File;

public class FileTest03 {
    public static void main(String[] args) {
        //获取当前目录下所有子文件
        File f = new File("D:/Study");
        File[] files = f.listFiles();
        for (File s : files){
            System.out.println(s);
        }
    }
}

拷贝目录

import java.io.File;

public class CopyAll {
    public static void main(String[] args) {
        File src = new File("D:\\Study\\Java");
        File dest = new File("C:\\test");
        copyDir(src, dest);
    }

    private static void copyDir(File src, File dest) {
        //获取源下面的子目录
        File[] files = src.listFiles();
        if (src.isFile()) {
            return;
        }
        for (File f : files) {
            //System.out.println(f.getAbsoluteFile());
            if (f.isDirectory()) {
                String srcDir = f.getAbsolutePath();
                String destDir = (dest.getAbsolutePath().endsWith("\\") ? dest.getAbsolutePath() : dest.getAbsolutePath() + "\\") + srcDir.substring(3);
                File newFile = new File(destDir);
                if (!newFile.exists()) {
                    newFile.mkdirs();
                }
            }

            //递归调用
            copyDir(f, dest);
        }
    }
}

6 IO+Properties的联合使用

以后经常改变的数据,可以单独写道一个文件中,使程序动态获取。

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

public class IOPropertiesTest {
    public static void main(String[] args) throws IOException {
        /*
        Properties是一个Map集合,key和value都是String类型。
        将userinfo文件中的数据加载到Properties对象中。
         */
        //新建一个输入流对象
        FileReader reader = new FileReader("D:\\Study\\Java\\Project\\IO流\\IO+Properties\\userinfo");
        //新建一个Map对象
        Properties pro = new Properties();
        //调用Properties对象的load方法将文件中的数据加载到Map对象
        pro.load(reader);
        System.out.println(pro.getProperty("username"));
        System.out.println(pro.getProperty("password"));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值