2.IO流

1、IO:Input/Output

表示了数据移动的方向
以程序为参照物:流入程序的叫输入流,流出程序的叫输出流。

1.1、按照流的方向分为:

输入流,输出流

InputStream/Reader
OutputStream/Writer
FileInputStream/FileReader
...
FileOutputStream/FileWriter
...

2.2、按照流的内容分为:

字节流,字符流
字节流是 8 位通用字节流,字符流是 16 位 Unicode 字符流

字节,流中的内容就是字节,字节流
字符,流中的内容就是字符,字符流

字节流
字符流
InputStream
OutputStream
Writer
Reader

2.认识文件

文件:File

2.1、File类的常用方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fgDmpSDy-1660830154274)(http://jinlingyuan.work/server/index.php?s=/api/attachment/visitFile&sign=c3b211120e7ad4ab9288b57834c5cad2)]
代码案例:IO流中部分方法使用,创建文件夹

public class Test {
    public static void main(String[] args) {
        // 显示桌面上的文件
        File deskTop = new File("E:\\BigDataWorkSpaces\\javaStudentVsCode");
        System.out.println(deskTop.isDirectory());      // 输出Boolean值
        File[] files = deskTop.listFiles();
        System.out.println("名字\t\t日期\t大小");
        // 转化为本地化
        SimpleDateFormat dfs = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        FileSystemView fsv = FileSystemView.getFileSystemView();
        for (File file: files) {
            String name = file.getName();

            // 创建日期
            Date d = new Date(file.lastModified());
            String date = dfs.format(d);
            String size = file.length()+"";     // 长度的单位是:字节
            String type = fsv.getSystemTypeDescription(file);
            System.out.println(name+"\t\t"+date+"\t"+size+"\t"+type);
        }


        // 创建文件夹
        File file = new File("E:\\BigDataWorkSpaces\\javaStudentVsCode\\a\\b\\c");
        System.out.println(file);
        System.out.println(file.exists());  // 是否存在该目录
        file.mkdir();   // 创建该目录,也就是单层目录
        System.out.println(file.exists());
        file.mkdirs();  // 创建该目录,+s可以创建多层目录
        System.out.println(file.exists());

    }
}

2.2、使用FileInputStream 读文本文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7CbqnvdM-1660830154276)(http://jinlingyuan.work/server/index.php?s=/api/attachment/visitFile&sign=500a02503882a9d2027a5e12a45c3d48)]

2.3、使用FileOutputStream 写文本文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Cc8h7DRy-1660830154277)(http://jinlingyuan.work/server/index.php?s=/api/attachment/visitFile&sign=a3d3f01f814d1aacdea23f7a236c0d81)]
代码案例:字节输入流

public class Test2 {
    public static void main(String[] args) throws IOException {
        // InputStream 字节输入流
        File file = new File("E:\\BigDataWorkSpaces\\javaStudentVsCode\\a\\b\\c\\a.txt");
        InputStream in = new FileInputStream(file);     // 泛化  此处检查异常

        System.out.println(in.read());      // 读到的具体内容
        System.out.println((char) in.read());   // 读到的数据转换成字符

        System.out.println("-------------");
        while (true){
            int n = in.read();
            if (n == -1){
                break;
            }
            System.out.println((char)n);
        }

        String s = "微";
        byte[] bb = s.getBytes();
        System.out.println(Arrays.toString(bb));
    }
}

2.4、复制文本文件

代码案例:文本,图片

public class Test3 {
    public static void main(String[] args) throws IOException{

        // new String(byte[])
        File file = new File("E:\\BigDataWorkSpaces\\javaStudentVsCode\\a\\b\\c");
        File file1 = new File("E:\\BigDataWorkSpaces\\javaStudentVsCode\\a\\b\\d");

        int count = 0;
        for (File fileNmae: file.listFiles()) {
            System.out.println(fileNmae);

            InputStream in = new FileInputStream(fileNmae);
            File file2 = new File(file1,count+".未知");
            OutputStream out = new FileOutputStream(file2);
            while (true){
                int n = in.read();
                if (n == -1){
                    break;
                }
                out.write(n);
            }
            out.close();
            in.close();
            count ++;
        }
        System.out.println("ok........");
    }
}

更多流学习

字符编码是GBK(国标)
文件中一个汉字占两个字节
一个阿拉伯数字和一个字母占一个字节
字符编码是UTF-8(万国码)
文件中一个汉字占三个字节
一个阿拉伯数字和一个字母占一个字节
字节输入流:FileInputStream  是用来读取
字节输出流:FileOutputStream  是用来写
字符输入流:FileReader
字符输出流:FileWriter
字符缓冲输入流:BufferedReader
字符缓冲输出流:BufferedWriter
二进制输入流:DataInputStream
二进制输出流:DataOutputStream
通常使用缓冲流去对文本读取写入
通常使用二进制流读取视频、图片、音乐…

1.DataOutputStream:数据输出流 并不是文本,是字节流
练习1:输出流

public class Test {
    public static void main(String[] args) throws IOException {
        String s = "我爱中国";
        int n = 21;
        double d = 99.9;

        // 输出流
        // DataOutputStream:数据输出流   并不是文本,是字节流
        // FileOutputStream:文件输出流
        DataOutputStream dos = new DataOutputStream(new FileOutputStream(new File("data.txt")));
        dos.writeUTF(s);
        dos.writeInt(n);
        dos.writeDouble(d);
		// 强制输出
        dos.flush();
        System.out.println("ok.................");
		// 关闭程序
		dos.close();
    }
}

2.DataInputStream:数据输入流 并不是文本,是字节流
练习2:输入流

public class Test2 {
    public static void main(String[] args) throws IOException {
        // 输入流
        DataInputStream dis = new DataInputStream(new FileInputStream(new File("data.txt")));

        String s = dis.readUTF();
        System.out.println(s);
        int i = dis.readInt();
        System.out.println(i);
        double d = dis.readDouble();
        System.out.println(d);
        // 关闭程序
        dis.close();
    }
}

缓冲流
BufferedInputStream BufferedOutputStream
BufferedReader
InputStreamReader 字节流转化字符流

package com.bigdata09.day15.demo1;

import java.io.*;

public class Test3 {
    public static void main(String[] args) throws Exception{

        //入流和出流
        InputStream in = new FileInputStream(new File("d:\\a\\b\\c\\m.jpg"));
        OutputStream out = new FileOutputStream(new File("src/main/resources/b.jpg"));
       // BufferedInputStream bin =new BufferedInputStream(in);
        //BufferedOutputStream bout = new BufferedOutputStream(out);

        System.out.println("开始拷贝");
        long start = System.currentTimeMillis();//计时⏲
        //bout.write(bin.readAllBytes()); //一次性读写
        /*int size = bin.available();
        int n = size/(1024*1024);
        int mod = size%(1024*1024);

        for (int i = 0; i < n; i++) {
            byte[] bytes =bin.readNBytes();
            bout.write(bytes);
            bout.flush();
        }
        bout.write(bin.readNBytes(mod));
        bout.flush();*/
        byte[] buffer = new byte[1024];
        while (true){

            int n = in.read(buffer); // n 不再表示字节 将表示读到的字节个数
            if (n < buffer.length){//1024) {
                out.write(buffer,0,n);
                out.flush();
                break;
            }
            out.write(n);
            out.flush();
        }
        long end = System.currentTimeMillis();
        long haoshi = end-start;

        out.close();
        in.close();
        System.out.println("ok......."+haoshi);
    }
}

PrintWriter 打印字符流(输出并换行)
ObjectOutputStream 字节流

3.案例:记账功能实现

public class Test {
    public static void main(String[] args) {
        /**
         * 1.记账
         * 2.结余
         * 3.账单
         * 4.退出
         */
        ZhangDans sys = new ZhangDans();
        sys.start();
    }
}
public class ZhangDan implements Serializable {
    private String type;
    private String money;
    private String mark;

    private final static long serialVersionUID = 1L;

    public ZhangDan() {
    }

    public ZhangDan(String type, String money, String mark) {
        this.type = type;
        this.money = money;
        this.mark = mark;
    }


    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getMoney() {
        return money;
    }

    public void setMoney(String money) {
        this.money = money;
    }

    public String getMark() {
        return mark;
    }

    public void setMark(String mark) {
        this.mark = mark;
    }

    @Override
    public String toString() {
        return "ZhangDan{" +
                "type='" + type + '\'' +
                ", money='" + money + '\'' +
                ", mark='" + mark + '\'' +
                '}';
    }
}
public class ZhangDans {
    private BufferedReader cin = new BufferedReader(new InputStreamReader(System.in));

    public void start() {
        // 所有退出使用异常
        while (true){
            // 显示菜单
            showMenu();
            // 输入选项
            String key = inputMenu();
            // 执行选项操作
            execute(key);
        }
    }

    // 执行选项操作
    private void execute(String key) {
        if ("1".equals(key)){
            jiZhang();
            System.out.println("开始记账");
        }
        if ("2".equals(key)){
            showJieYu();
            System.out.println("显示结余");
        }
        if ("3".equals(key)){
            List<ZhangDan> list = showZhangDans();
            for (ZhangDan z: list) {
                System.out.println(z);
            }
            System.out.println("显示历史账单");
        }
        if ("4".equals(key)){
            System.out.println("------------");
            throw new RuntimeException("不要惊讶,你没错,我只使用这个退出");
        }
    }

    // 结余
    private void showJieYu() {
        List<ZhangDan> list = showZhangDans();
        double yuE = 0;
        double shouRu = 0;
        double zhiChu = 0;
        for (ZhangDan zDan:list) {
            if ("1".equals(zDan.getType())){
                yuE += Double.parseDouble(zDan.getMoney());
                shouRu += Double.parseDouble(zDan.getMoney());
            }
            if ("2".equals(zDan.getType())){
                yuE -= Double.parseDouble(zDan.getMoney());
                zhiChu += Double.parseDouble(zDan.getMoney());
            }
        }
        System.out.println("总余额:"+yuE+"\t总收入:"+shouRu+"\t总支出:"+zhiChu);
    }

    // 显示历史账单
    private List<ZhangDan> showZhangDans() {
        /*try (BufferedReader bufferedReader = new BufferedReader(new FileReader(new File("day30/src/main/resources/zhangdan30.txt")))) {
            while (true){
                String line = bufferedReader.readLine();
                if (line == null){
                    break;
                }
                System.out.println(line);
            }
        } catch (IOException e) {
            System.out.println(e.getMessage());
            throw new RuntimeException("账单查询失败并退出");
        }*/

        // ↑  上和下  ↓ 都能实现

        // 反序列化
        try (ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(new File("day30/src/main/resources/zhangdan30.txt")))) {
            List<ZhangDan> list = (List<ZhangDan>) objectInputStream.readObject();

            return list;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return new ArrayList<>();
    }

    // 记账功能
    private void jiZhang() {
        System.out.println("类型:1:收入  2:支出");
        String type = inputType();
        System.out.println("金额:");
        String money = inputMoney();
        System.out.println("说明");
        String mark = inputMark();
        ZhangDan zhangDan = new ZhangDan(type,money,mark);
        saveZhangDan(zhangDan);
        System.out.println("登记成功"+zhangDan);
    }

    private void saveZhangDan(ZhangDan zhangDan) {
        /*// 输出流
        try (PrintWriter printWriter = new PrintWriter(new FileWriter(new File("day30/src/main/resources/zhangdan30.txt"),true))){
            printWriter.println(zhangDan);
            printWriter.flush();
        } catch (IOException e) {
            System.out.println(e.getMessage());
            throw new RuntimeException("账单保存失败并退出");
        }*/

        // ↑  上和下  ↓ 都能实现

        // 序列化流
        File file = new File("day30/src/main/resources/zhangdan30.txt");
        List<ZhangDan> list = new ArrayList<>();
        if (file.exists()){
             list = showZhangDans();
        }
        list.add(zhangDan);
        try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(new File("day30/src/main/resources/zhangdan30.txt")))) {
            objectOutputStream.writeObject(list);
            // 刷新
            objectOutputStream.flush();
            objectOutputStream.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 说明
    private String inputMark() {
        String s = null;
        try {
            s = cin.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return s;
    }

    // 金额
    private String inputMoney() {
        while (true){
            try {
                String money = cin.readLine();
                // 留待学习更多知识后优化,验证,输入的必须是数字
                int count = 0;
                for (int i = 0; i < money.length(); i++) {
                    char c = money.charAt(i);
                    if (c >= '0' && c <= '9'){
                        continue;
                    }
                    if (c == '.' && count == 0){
                        count++;
                        continue;
                    }
                    throw new Exception("您输入的不是数字!");
                }
                return money;
            } catch (IOException e) {
                e.printStackTrace();
            }catch (Exception e){
                System.out.println(e.getMessage());
            }
        }
    }


    // 类型
    private String inputType() {
        while (true){
            try {
                String type = cin.readLine();
                if ("1".equals(type) || "2".equals(type)){
                    return type;
                }
                throw new Exception("类型选项不对,你只能输入1或者2!");
            } catch (IOException e) {
                e.printStackTrace();
            }catch (Exception e){
                System.out.println(e.getMessage());
            }
        }
    }

    // 输入菜单
    private String inputMenu() {
        while (true){
            try {
                String key = cin.readLine();
                if ("1".equals(key) || "2".equals(key) || "3".equals(key) || "4".equals(key)){
                    return key;
                }
                throw new Exception("您输入的数字范围不对");
            } catch (IOException e) {
                System.out.println("出现异常重试一次");
            }catch (Exception e){
                System.out.println(e.getMessage());
            }
        }
    }

    // 显示菜单
    private void showMenu() {
        System.out.println("1.记账\n" +
                "           2.结余\n" +
                "           3.账单\n" +
                "           4.退出");
        System.out.println("输入选项吧:");
    }
}

4.序列化,反序列化

public class Test {
    public static void main(String[] args) {
        ZhangDan zhangDan = new ZhangDan("1","77","测试");
        // 出流   输出对象类型的数据

        // 序列化和反序列化的前提条件是:实现序列化接口 :implements Serializable
        // 序列化流
        try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(new File("day30/src/main/resources/data.d")))) {
            objectOutputStream.writeObject(zhangDan);
            // 刷新
            objectOutputStream.flush();
            objectOutputStream.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 反序列化
        try (ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(new File("day30/src/main/resources/data.d")))) {
            ZhangDan zhangDan1 = (ZhangDan)(objectInputStream.readObject());
            System.out.println(zhangDan1);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

5.NI/O相关知识

NIO(Non-blocking I/O,在Java领域,也称为New I/O),是一种同步非阻塞的I/O模型,也是I/O多路复用的基础,已经被越来越多地应用到大型应用服务器,成为解决高并发与大量连接、I/O处理问题的有效方式。

NIO主要有三大核心部分:Channel(通道),Buffer(缓冲区), Selector。传统IO基于字节流和字符流进行操作,而NIO基于Channel和Buffer(缓冲区)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。Selector(选择区)用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个线程可以监听多个数据通道。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值