java03 IO操作

本文详细介绍了Java中的IO流概念及应用,包括节点流与处理流的区别、输入输出流的基础操作、文件流的具体实现、缓冲流如何提升读写效率、对象序列化与反序列化的原理及实践、以及字符流Reader和Writer的使用技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

注意: 不要在main函数上throws异常,这里为了方便,我就这样写了。

一、节点流和处理硫

1.1 节点流

也称为低级流,可以从或向一个特定的地方(节点读写数据)

1.2 处理流

也称为高级流,对一个已存在的连接和封装,通过所封装的流的功能调用实现数据读写。

处理流的构造方法总要带一个其他流对象做参数。一个流对象经过其他流的多次包装,成为流的链接。

1.3 低级流和高级流理解

读写,可以没有高级流,但是一定要有低级流(数据源是明确的)

二、输入输出流

2.1 输入流

InputStream是所有字节输入流的父类,定义了基础的读取方法,常用方法有:
1. int read()
读取一个字节,以int形式返回,该int值的”低八位”有效,若返回值为-1表示EOF
2. int read(byte[] d)
尝试最多读取给定数据length个字节并存入该数组,返回值为实际读取到的字节量

2.2 输出流

OutputStream是所有字节输出流的父类,其定义了基础的写出方法,常用的方法有:
1. void write(int d)
写出一个字节,写的是给定的int的”低八位”
2. void write(byte[] d)
将给定的字节数组中的所有字节全部写出

三、文件流(低级流)

public class FileStreamDemo {

    /**
     * 讲了文件流输出用法
     * @throws IOException
     */
    public static void fileOutPut() throws IOException{
        // 没有该文件会创建文件,如果该文件存在,默认会清空原有内容,然后再输出
        /*
         * 在创建时,如果指定第二个参数,并且指定该值为true,那么本次通过fos写出的内容会被追加到该文件末尾
         * 
         * */
        FileOutputStream fos = new FileOutputStream("fos.txt", true);

        String str = "我是圆滚滚";
        // string转换成字节,指定编码为utf-8
        byte[] data = str.getBytes("utf-8");
        fos.write(data);
        fos.close();
    }

    /**
     * 讲了文件流输入用法
     * @throws IOException
     */
    public static void fileInput() throws IOException{
        FileInputStream fiStream = new FileInputStream("fos.txt");
        byte[] data = new byte[100];
        int len = fiStream.read(data);
        String str = new String(data,0, len, "utf-8");
        System.out.println(str);
    }

    public static void main(String[] args) throws IOException {
        // fileOutPut();
        fileInput();
    }
}

四、缓冲流(高级流)

/**
 * 这个类主要是讲了缓冲流的使用
 *      缓冲流其实内部也是定义一个buffer数组(一定大小的缓冲池)的方式来提高读写效率,将慢速的硬盘IO,变为缓存中的数据读取
 * @author Gupan
 *
 */
public class CacheStreamDemo {
    public static void main(String[] args) throws IOException {
        FileInputStream fiStream = new FileInputStream("fos.txt");
        // 给fiStream加上缓存流
        BufferedInputStream bis = new BufferedInputStream(fiStream);

        FileOutputStream foStream = new FileOutputStream("fos.txt");
        // 给foStream加上缓存流
        BufferedOutputStream bos = new BufferedOutputStream(foStream);

        int d = -1;
        while((d = bis.read()) != -1) {
            bos.write(d);
        }

        System.out.println("复制完毕");

        // 在缓冲区没有满的时候,强制把缓冲区的东西刷到硬盘上
        bos.flush();
        // 关闭高级流,会将其中封装的高级流以及低级流都关闭了
        bis.close();
        bos.close();

    }
}

五、对象流

5.1 对象序列化

将一个对象转换为一组字节的过程

5.2 对象持久化

将该对象的字节写入到硬盘,做长久保存

5.3 反序列化

/**
 * 这个类主要讲了对象流的用法
 *      对象流的作用是方便读写java中的对象
 * 
 * 对象输出流:
 *      可以将给定的对象转换为一组字节后写出
 * 对象输入流:
 *      
 * 
 * @author Gupan
 *
 */

// 对于一个对象,如果想要使用对象流,存储对象实例,需要实现Serializable接口,这是一个抽象接口,没有任何接口方法,
// 但是编译器在编译时,会识别哪些类实现了这个接口,并做一些底层的事情,类似Serializable的接口也叫做签名接口
/*
 * 
 *
 * 实现Serializable接口后,需要加上一个版本号serialVersionUID,不然会有警告。如果不写serialVersionUID,系统默认会更具类的接口生成一个版本号
 * (这个版本号会随类的结构变化而变化,但是在类结构变化的情况下,由于序列化和反序列化的版本号不同,反序列化就会报错,自定义版本号可以避免上述情况,
 * 在版本号一致,但是类的结构改变的情况下,改变的属性移除消失,新增的属性取默认值)
 * */
public class ObjectStreamDemo implements Serializable{
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private String name;
    private int age;
    private String gender;

    // 当一个类使用了Serializable接口以后,就可以实现一个关键字transient
    // 当一个类的实例在进行序列化的时候,加了transient关键字的属性在序列化时就不会序列化,这样做的意义是存储对象的瘦身
    private List <String> otherInfo;

    public ObjectStreamDemo() {
    }

    public ObjectStreamDemo(String name, int age, String gender,List <String> otherInfo) {
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.otherInfo = otherInfo;
    }

    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return this.name + "," + this.age + "," + this.gender + "," + this.otherInfo;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public List<String> getOtherInfo() {
        return otherInfo;
    }

    public void setOtherInfo(List<String> otherInfo) {
        this.otherInfo = otherInfo;
    }



    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectStreamDemo p = new ObjectStreamDemo();
        p.setName("圆滚滚");
        p.setAge(18);
        p.setGender("男");
        List <String> otherInfo = new ArrayList<String> ();
        otherInfo.add("是一个学生");
        otherInfo.add("2018年毕业");
        p.setOtherInfo(otherInfo);

        // *************************************************对象序列化*************************************************
        FileOutputStream fos = new FileOutputStream("info.txt");

        // 使用对象流
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        // 进行对象持久化
        oos.writeObject(p);

        oos.flush();
        oos.close();

        // *************************************************对象反序列化*************************************************
        FileInputStream fiStream = new FileInputStream("info.txt");
        ObjectInputStream ois = new ObjectInputStream(fiStream);
        ObjectStreamDemo pRe = (ObjectStreamDemo) ois.readObject();
        System.out.println(pRe);
        ois.close();

    }
}

六、 Reader和Writer

字符输入流和字符输出流的顶级父类,字符流是以字符为单位读写数据的。一次处理一个unicode。字符流的底层仍然是基本的字节流,所有的字符流都是高级流

6.1 Reader的常用方法


  1. int read()

读取一个字符,返回的int值“低16”位有效
  • int read(char[] chs)
    从该流中读取一个字符数组的length个字符并存入该数组,返回值为实际读取到的字符量

6.2 Writer的常用方法


  1. void write(int c)

写出一个字符,写出给定int值“低16位”表示的字符
  • void write(char [] chs)
    将给定的字符数组中所有字符写出
  • void write(String str)
    将给定的字符串写出
  • void write(char[] chs, int offset, int len)
    将给定的字符数组从offset出开始连续的len铬字符写出

6.3 常用的Reader和Writer

6.3.1 InputStreamReader和OutputStreamWriter

完成字符流向字节流的转换,通过这两个字符流转换以后,其他的字符流才可以处理
1. InputStreamReader
代表字符输入流,可以按照指定的字符集从流中按照编码将字节数据转换为字符并读取
2. OutputStreamWriter
代表字符输出流,使用该流可以设置字符集,并按照指定的字符集将字符转换为对应的字节后用过该流写出

public class ReaderAndWriterDemo {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("osw.txt");
        OutputStreamWriter osw = new OutputStreamWriter(fos, "utf-8");
        osw.write("圆滚滚在向前滚");
        osw.close();

        FileInputStream fis = new FileInputStream("osw.txt");
        InputStreamReader isr = new InputStreamReader(fis, "utf-8");

        int d = -1;
        while ((d = isr.read()) != -1) {
            System.out.print((char)d);
        }
    }
}

6.3.2 BufferedWriter和BufferedReader

特点

按行读写字符串

6.3.3 PrintWriter


  1. PrintWriter

具有自动行刷新缓冲字符输出流,在创建时,他一定会在内存创建BufferedWriter作为缓冲功能的叠加
/**
 * 这个类主要讲了缓冲字符流的用法
 * 
 * @author Think
 *
 */
public class PrintWriterDemo {
    public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
        // 内部帮我们创建了File对象
        PrintWriter pw = new PrintWriter("pw.txt", "utf-8");

        pw.println("圆滚滚在向前滚");
        pw.println("滚得越来越远了");
        pw.close();

        FileOutputStream fos = new FileOutputStream("pw.txt", true);
        // 构造方法内部有创建字符流,但是这种方式不能指定字符集,如果要指定字符集,那么指定一
        // 个OutputStreamWriter对象,创建时指定字符集
        pw = new PrintWriter(fos);
        pw.println("滚得又远了一点");
        pw.close();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值