IO流

io流框架

流的概念

  • 流是内存与存储设备传输数据通道
  • 水相当于数据,传输水管道相当于流

image-20230424151101867

流的分类

  1. 按方向
    • 输入流:从存储设备->内存
    • 输出流:从内存->存储设备
  2. 按单位
    • 字节流:以字节为单位,可以读写所有数据,所有数据都是字节B为单位
    • 字符流:以字符为单位,只能读写文本数据,字符(1B,2B。。。都可能)
  3. 按功能
    • 节点流:实现读写数据
    • 过滤流:增强结点流

字节流

  • 字节流父类
  • InputStream:字节输入流,抽象
  • OutputStream:字节输出流,抽象

FileInputStream类

  • InputStream的实现类
  • read(),每次读取一个字节,返回读取的ascii码
  • read(bytes),读取多个,数量为数组bytes长度,返回读取的长度
  • close关闭
package com.Io;

import java.io.FileInputStream;
import java.util.Arrays;


// FileInputStream
public class Demo01 {
    public static void main(String[] args) throws Exception{
        // 指定路径
        FileInputStream fis = new FileInputStream("F:\\ava\\1.txt");
        // 1返回字符对应ascii码
//        int n = 0;
//        while ((n=fis.read())!=-1){
//            System.out.println((char) n);
//        }
        // 2返回此次读取长度
//        byte[] bytes = new byte[3];
//        int count1 = fis.read(bytes);
//        System.out.println(count1);
//        System.out.println(new String(bytes));
//
//        int count2 = fis.read(bytes);
//        System.out.println(count2);
//        System.out.println(new String(bytes));

        // 3循环多次读取
        byte[] bytes = new byte[1024];
        int count = 0;
        while ((count=fis.read(bytes))!=-1){
            System.out.println(count);
            System.out.println(new String(bytes,0,count));
        }

        fis.close();

    }
}

FileOutputStream类

  • OutputStream的实现类
  • write(x),将ascii码x对应的字符写入
  • write(bytes),将字符数组bytes写入
  • close(),关闭
package com.Io;

import java.io.FileOutputStream;

// FileOutputStream
public class Demo02 {
    public static void main(String[] args) throws Exception{
        // 方法无true,文件是先清空原来,再写,反之则继续写
        FileOutputStream fos = new FileOutputStream("F:\\ava\\2.txt",true);
        fos.write('a');
        fos.write('b');
        fos.write('c');
        fos.write(97);

        String s = "hello world";
        fos.write(s.getBytes());

        fos.close();
    }
}

  • 实现文件复制
    1. 通过输入流,将存储数据->内存,存于内存byte[]数组中
    2. 通过输出流,将内存数组->存储设备
package com.Io;

import java.io.FileInputStream;
import java.io.FileOutputStream;

public class Demo03 {
    public static void main(String[] args) throws Exception{
        FileInputStream fis = new FileInputStream("F:\\ava\\1.jpg");
        FileOutputStream fos = new FileOutputStream("F:\\ava\\2.jpg",true);

        int count = 0;
        byte[] bytes = new byte[1024];
        while ((count=fis.read(bytes))!=-1){
            System.out.println(count);
            fos.write(bytes,0,count);
        }
        fis.close();
        fos.close();
    }
}

字节缓冲流

  • 设有缓冲区,提高io效率,减少访问磁盘次数

BufferedInputStream类

  • 父类FilterInputStream,父父类InputStream
  • FilterInputStream过滤流,加强型节点流,节点流FileInputStream,有基础的读写方法
  • BufferInputStream,字节缓冲流,BufferInputStream设有缓冲区,提高io效率,减少访问磁盘次数
  • 普通节点流需要多次读取,因为没有缓存区
package com.Io;

import java.io.BufferedInputStream;
import java.io.FileInputStream;

// BufferInputStream
public class Demo04 {
    public static void main(String[] args) throws Exception{
        FileInputStream fis = new FileInputStream("F:\\ava\\1.txt");
        BufferedInputStream bis = new BufferedInputStream(fis);// 增强fis

//        int data = 0;
//        while ((data=bis.read())!=-1){
//            System.out.println((char) data);
//        }

        int count = 0;
        byte[] bytes = new byte[1024];
        while ((count=bis.read(bytes))!=-1){
            System.out.println(new String(bytes,0,count));
        }
        bis.close();

    }
}

BufferedOutputStream类

  • 继承关系和上一样
  • 将数据先写入缓存区,满了或者调用flush方法,再写入底层系统,不用一个一个写
  • flush会刷新缓冲区,把缓冲区数据写入底层系统
package com.Io;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;

// BufferOutputStream
public class Demo05 {
    public static void main(String[] args) throws Exception{
        FileOutputStream fos = new FileOutputStream("F:\\ava\\buffer.txt");
        BufferedOutputStream bis = new BufferedOutputStream(fos);

        String s = "hello pixiv\n";
        for (int i = 0; i < 10; i++) {
            bis.write(s.getBytes());// 写入缓存区
            bis.flush();// 刷新缓存区到存储文件
        }

        // 默认内调用flush
        bis.close();
    }
}

对象流

  • ObjectOutputStream/ObjectInputStream
  • 增强了缓冲区功能
  • 增强了读写8种基本数据类型和字符串功能,可以操作对象
  • 序列化:writeObject(Object obj),向流写入一个对象,内存->存储设备
  • 反序列化:readObject(),从流读取一个对象,存储设备->内存

序列化/ObjectOutputStream类

  • ObjectOutputStream类

  • 序列化,写入操作,写入对象到存储中

  • 对应对象需要实现接口Serializable(可序列化的),只是一个标记,没重写的方法

    public class Student implements Serializable
    
package com.Io;

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;

public class Demo06 {
    public static void main(String[] args) throws Exception{
        FileOutputStream fos = new FileOutputStream("F:\\ava\\stu.bin");
        ObjectOutputStream oos = new ObjectOutputStream(fos);

        Student s1 = new Student("乐",10);

        // 序列化(写入操作)
        oos.writeObject(s1);

        oos.close();
    }
}

反序列化/ObjectInputStream类

  • ObjectInputStream类
  • 反序列化,读取操作,读取对象到内存
  • 需要实现接口Serializable(可序列化的)
  • 不能读取对象多次,会出现EOF异常,endoffile
package com.Io;

import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class Demo07 {
    public static void main(String[] args) throws Exception{
        FileInputStream fio = new FileInputStream("F:\\ava\\stu.bin");
        ObjectInputStream ois = new ObjectInputStream(fio);

        // 反序列化,读取操作,不能读取多次
        Student student = (Student)ois.readObject();
//        Student student1 = (Student)ois.readObject();

        ois.close();
        System.out.println(student);


    }
}

序列化注意事项

  • 序列化类必须实现Serializable接口

  • 类内的对象属性要求实现Serializable类,例如Student类内有一个Person对象,Person需要实现Serializable接口

  • 序列化版本号ID,保证序列化类和反序列化类是同一个类

    private static final long serialVersionUID = 100L;
    
  • 关键字,transient(瞬间的),不能序列化,显示默认值0或null

  • 静态属性不能序列化,序列化是长保存

  • 可以多次写入实现多次读取

  • 通过集合实现多个对象的序列化和反序列化

        Student s1 = new Student("乐",10);
        Student s2 = new Student("孝",12);

        ArrayList<Student> arrayList = new ArrayList<>();
        arrayList.add(s1);
        arrayList.add(s2);

        // 序列化(写入操作)
        oos.writeObject(arrayList);
        // 反序列化,读取操作,不能读取多次
        ArrayList<Student> arrayList = (ArrayList<Student>) ois.readObject();
//        Student student1 = (Student)ois.readObject();

        ois.close();
        System.out.println(arrayList);

字符流

字符编码

  • UTF-8 针对Unicode码表的可变长度字符编码
  • ISO-8856-1 asii码,西欧,希腊,泰语,阿拉伯,希伯来语对应文字符号
  • GB2312 简中
  • GBK 简中,简中
  • BIG5 台湾,繁中

Reader和Writer

  • 两抽象类Reader和Writer
  • 子子类为FileReader和FileWriter

FileReader类

  • 实现输入流,通过字符读取,每次字节数不一定
  • FileInputStream,中文因为utf-8规定,一个汉字3个字节,普通字节流的单次读取为一次一个字节,会无法读取,不过数组读取也可以
package com.Io;

import java.io.FileReader;

public class Demo08 {
    public static void main(String[] args) throws Exception{
        FileReader fr = new FileReader("F:\\ava\\3.txt");
//        int data = 0;
//        while ((data=fr.read())!=-1){// 一次一个字符char
//            System.out.print((char) data);
//        }

        char[] chars = new char[1024];
        int count = 0;
        while ((count=fr.read(chars))!=-1){
            System.out.println(new String(chars,0,count));
        }


    }
}

FileWriter类

  • 实现输出流,通过字符输出
package com.Io;

import java.io.FileWriter;

public class Demo09 {
    public static void main(String[] args) throws Exception{
        FileWriter fw = new FileWriter("F:\\ava\\3.txt");
        String s = "java是世界最好语言";
        // 写入
        fw.write(s);// 可以直接写入字符和字符串,不用非要写入字节
        // 刷新
        fw.flush();
        // 关闭
        fw.close();
    }
}
  • 字符流复制文件
  • 字符流不能复制图片,二进制文件,因为图片没有字符编码,read读取到内存变为乱码
package com.Io;

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

// 字符流实现复制
// 字符流只能复制文本文件,不能复制二进制和图片
// 字节流都可以,因为所有文件都是字节组成
public class Demo10 {
    public static void main(String[] args) throws Exception{
        FileWriter fw = new FileWriter("F:\\ava\\n.txt");
        FileReader fr = new FileReader("F:\\ava\\o.txt");

        int count = 0;
        char[] chars = new char[1024];
        while ((count=fr.read(chars))!=-1){// 读取o到chars
            System.out.println(new String(chars,0,count));
            fw.write(chars,0,count);// chars写入n
            fw.flush();
        }

        fw.close();
        fr.close();

    }
}

字符缓冲流

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

BufferedReader类

  • 字符缓存输入流
  • 可以自建缓冲区char[],也可以readline(),读一行
package com.Io;

import java.io.BufferedReader;
import java.io.FileReader;

public class Demo11 {
    public static void main(String[] args) throws Exception{
        FileReader fr = new FileReader("F:\\ava\\3.txt");
        BufferedReader br = new BufferedReader(fr);

//        // 自建缓存区读取
//        int count = 0;
//        char[] chars = new char[1024];
//
//        while ((count= br.read(chars))!=-1){
//            System.out.println(new String(chars,0,count));
//        }

        // 读一行,读到结束返回null
        String s = null;
        while ((s=br.readLine())!=null){
            System.out.println(s);
        }
    }
}
@Service
public class SetmealServiceImpl extends ServiceImpl<SetmealMapper, Setmeal> implements SetmealService {
    @Autowired
    protected SetmealDishService setmealDishService;

    @Override
    public void saveWithDish(SetmealDto setmealDto) {
        this.save(setmealDto);
        List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();
        setmealDishes = setmealDishes.stream().map((item) -> {
            item.setSetmealId(setmealDto.getId());
            return item;
        }).collect(Collectors.toList());
        setmealDishService.saveBatch(setmealDishes);
    }
}
posted @ 2025-04-22 22:06  学习java的白菜  阅读(49)  评论(0)    收藏  举报